CodeForces 348D Turtles(LGV定理)题解

题意:两只乌龟从1 1走到n m,只能走没有'#'的位置,问你两只乌龟走的时候不见面的路径走法有几种

思路:LGV定理模板。但是定理中只能从n个不同起点走向n个不同终点,那么需要转化。显然必有一只从1, 2走到 n - 1, m,另一只从2, 1走到 n, m - 1。

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 3000 + 10;
const int M = maxn * 30;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1000000007;
char mp[maxn][maxn];
ll dp[maxn][maxn];
ll e[5][5];
ll guass(int n, ll p){
    ll ans = 1, f = 1;
    for(int i = 1; i <= n; i++){
        for(int j = i + 1; j <= n; j++){
            int x = i, y = j;
            while(e[y][i]){
                ll t = e[x][i] / e[y][i];
                for(int k = i; k <= n; k++)
                    e[x][k] = (e[x][k] - e[y][k] * t % p) % p;
                swap(x,y);
            }
            if(x != i){
                for(int k = 1; k <= n; k++)
                    swap(e[i][k], e[j][k]);
                f = -f;
            }
        }
        ans = ans * e[i][i] % p;
        if(ans == 0) return 0;
    }
    return (ans * f + p) % p;
}
int main(){
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++)
        scanf("%s", mp[i] + 1);
    memset(dp, 0, sizeof(dp));
    dp[1][2] = 1;
    for(int i = 1; i <= n; i++){
        for(int j = 2; j <= m; j++){
            if(i == 1 && j == 2) continue;
            if(mp[i][j] == '#') continue;
            dp[i][j] = 0;
            if(j - 1 >= 1 && mp[i][j - 1] != '#')
                dp[i][j] += dp[i][j - 1];
            if(i - 1 >= 1 && mp[i - 1][j] != '#')
                dp[i][j] += dp[i - 1][j];
            dp[i][j] = dp[i][j] % MOD;
        }
    }
    e[1][1] = dp[n - 1][m], e[1][2] = dp[n][m - 1];
    memset(dp, 0, sizeof(dp));
    dp[2][1] = 1;
    for(int i = 2; i <= n; i++){
        for(int j = 1; j <= m; j++){
            if(i == 2 && j == 1) continue;
            if(mp[i][j] == '#') continue;
            dp[i][j] = 0;
            if(j - 1 >= 1 && mp[i][j - 1] != '#')
                dp[i][j] += dp[i][j - 1];
            if(i - 1 >= 1 && mp[i - 1][j] != '#')
                dp[i][j] += dp[i - 1][j];
            dp[i][j] = dp[i][j] % MOD;
        }
    }
    e[2][1] = dp[n - 1][m], e[2][2] = dp[n][m - 1];
    printf("%lld
", guass(2, MOD));
    return 0;
}
原文地址:https://www.cnblogs.com/KirinSB/p/10816321.html