hdu 5852(求n个起点到n个终点的不想交路径+ 行列式计算)

Intersection is not allowed!

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 485    Accepted Submission(s): 168


 

Problem Description

There are K pieces on the chessboard.

The size of the chessboard is N*N.

The pieces are initially placed on the top cells of the board.

A piece located on (r, c) can be moved by one cell right to (r, c + 1) or one cell down to (r+1, c).

Your task is to count how many different ways to move all pieces to the given positions at the bottom of the board.

Furthermore, the paths of the pieces mustn’t intersect each other.

 

Input

The first line of input contains an integer T-the number of test cases.

Each test case begins with a line containing two integers-N(1<=N<=100000) and K(1<=K<=100) representing the size of the chessboard and the number of pieces respectively.

The second line contains K integers: 1<=a1<a2< …<aK<=N representing the initial positions of the pieces. That is, the pieces are located at (1, a1), (1, a2), …, (1, aK).

Next line contains K integers: 1<=b1<b2<…<bK<=N representing the final positions of the pieces. This means the pieces should be moved to (N, b1), (N, b2), …, (N, bK).

 

Output

Print consecutive T lines, each of which represents the number of different ways modulo 1000000007.

 

Sample Input

 

1 5 2 1 2 3 4

 

Sample Output

 

50

 

Author

金策工业综合大学(DPRK)

 

思路: 定理: https://en.wikipedia.org/wiki/Lindström–Gessel–Viennot_lemma

用来求 n个起点到n个终点的不想交路径。 转化成组合数学的问题。 

代码: 

#include<bits/stdc++.h>
#define LL long long
using namespace std;
typedef long long ll;
typedef pair<int ,int > pii;
const int N =200005;
const int maxn =105;
const ll mod=1e9+7;

ll inv[N] = {1,1};  //inv[i] i的逆元。
ll fac[N] = {1,1};    // fac[i] i!%mod
ll facv[N] = {1,1};   // facv[i] i!的逆元
void init()
{
    for(int i = 2 ; i < N ; i ++)
        inv[i] = (mod-mod/i) * inv[mod%i] % mod;
    for(int i = 2 ; i < N ; i ++)
        facv[i] = facv[i-1] * inv[i] % mod;
    for(int i = 2 ; i < N ; i ++)
        fac[i] = fac[i-1]*i % mod;
}
ll C(ll n,ll m)
{
    if(m < 0) return 0;
    return fac[n]*facv[m]%mod*facv[n-m]%mod;
}

int quick_pow(ll n,ll m){
    LL s=1;
    LL k=n;
    while(m){
        if(m&1){
            s=s*k;
            s%=mod;
        }
        k=k*k;
        k%=mod;
        m>>=1;
    }
    return s;
}

ll dp[maxn][maxn];

int Gauss(int n) {
    int col = 0, k;
    LL ans = 1;
    for(k = 0; k < n && col < n; ++k, ++col) {
        if(dp[k][col] == 0) {
            for(int i = k + 1; i < n; ++i) {
                if(!(dp[i][col] == 0)) {
                    for(int j = col; j < n; ++j) swap(dp[k][j], dp[i][j]);
                    ans *= -1;
                    break;
                }
            }
        }
        int x = dp[k][col];
        ans *= x;
        ans %=  mod;
        for(int i = k + 1; i < n; ++i) {
            int y = dp[i][col];
            if(x == 0 || y == 0) continue;
            int d = __gcd(abs(x),abs(y));
            LL lcm = abs((LL)x * y / d);
            LL tx = lcm / x,ty = lcm / y;
            for(int j = col; j < n; ++j) {
                dp[i][j] = (-tx * dp[k][j] + ty * dp[i][j])%mod;
            }
            ans = (ans * quick_pow(ty,mod-2)) % mod;
        }
    }
    ans %= mod;
    ans += mod;
    ans %= mod;
    return ans;
}

int n,k;

pii st[N],en[N];

int main()
{
    init();
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d %d",&n,&k);
        for(int i=0;i<k;i++){
            scanf("%d",&st[i].second);
            st[i].first=1;
        }
        for(int i=0;i<k;i++){
            scanf("%d",&en[i].second);
            en[i].first=n;
        }

        ll mu,zi;
        zi=n-1;
        for(int i=0;i<k;i++){
            for(int j=0;j<k;j++){
                mu=en[j].second-st[i].second;
                if(mu<0){
                    dp[i][j]=0;
                }
                else{
                    mu+=zi;
                    dp[i][j]=C(mu,zi);
                    dp[i][j]%=mod;
                }
            }
        }

        ll ans=Gauss(k);
        printf("%lld\n",ans);

    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/yjt9299/article/details/81153317
今日推荐