hdu 5852 Intersection is not allowed! (2016多校第九场1009)组合

来源:互联网 发布:java 模块化 编辑:程序博客网 时间:2024/06/16 17:55

这是一道公式题,虽然想了半天也想不出来,https://en.wikipedia.org/wiki/Lindström–Gessel–Viennot_lemma看这个就行了。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;typedef long long LL;const int maxn=200005;const int mod=1000000007;int jie[maxn];int jie1[maxn];int mm(int n,int 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;}void init(){    jie[0]=1;    jie1[0]=1;    for(int i=1;i<maxn;i++){        jie[i]=((LL)jie[i-1]*i)%mod;        jie1[i]=mm(jie[i],mod-2);    }}int zuhe(int n,int m){    if(n<m) return 0;    LL s=jie[n];    s=s*jie1[n-m];    s%=mod;    s=s*jie1[m];    s%=mod;    return s;}int a[maxn],b[maxn];int mat[500][500];int gcd(int a,int b){    if(b==0) return a;    return gcd(b,a%b);}int Gauss(int n) {    for (int i = 0; i < n; i++) {        for (int j = 0; j < n; j++)            mat[i][j] = (mat[i][j] + mod) % mod;    }    int col = 0, k;    LL ans = 1;    for(k = 0; k < n && col < n; ++k, ++col) {        if(mat[k][col] == 0) {            for(int i = k + 1; i < n; ++i) {                if(!(mat[i][col] == 0)) {                    for(int j = col; j < n; ++j) swap(mat[k][j], mat[i][j]);                    ans *= -1;                    break;                }            }        }        int x = mat[k][col];        ans *= x;        ans %=  mod;        for(int i = k + 1; i < n; ++i) {            int y = mat[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) {                mat[i][j] = (-tx * mat[k][j] + ty * mat[i][j])%mod;            }            ans = (ans * mm(ty,mod-2)) % mod;        }    }    ans %= mod;    ans += mod;    ans %= mod;    return ans;}int main(){    int t,n,m;    cin>>t;    init();    while(t--){        scanf("%d%d",&n,&m);        for(int i=1;i<=m;i++) scanf("%d",&a[i]);        for(int i=1;i<=m;i++) scanf("%d",&b[i]);        for(int i=1;i<=m;i++){            for(int j=1;j<=m;j++){                mat[i-1][j-1]=zuhe(b[j]-a[i]+n-1,n-1);            }        }        printf("%d\n",Gauss(m));    }}


0 0