zoukankan      html  css  js  c++  java
  • Intersection is not allowed!

    给出n∗n网格,顶部有k个起点,底部有k个相对应的终点
    每次只能向下或向右走
    求有多少种从各个起点出发到达对应终点且路径不相交的路径?(对109+7取模)


    n*m空间从左上角走到右下角只走右或者下的方案数位C(n,n+m)

    首先考虑两个棋子的情况,即一个棋子从a1到b1,另一个棋子从a2到b2不考虑交叉方案数显然是C(b1-a1+n-1,n-1) * C(b2-a2+n-1,n-1)

    对于路径交叉的方案,对于一个a1->b2,a2->b1的方案,这两条路径必然会相交,

    把最后一个交叉点之后的两条路径交换就又对应一个a1->b1,a2->b2的路径交叉的方案

    故我们建立了a1->b1,a2->b2交叉路径与a1->b2,a2->b1的方案的一一对应,那么不合法方案数就是C(b2-a1+n-1,n-1) * C(b1-a2+n-1,n-1)

    多个棋子的情况,考虑容斥,如果两个路径相交,相当于交换了终点

    枚举每个起点的终点,乘上一个容斥系数(1)tt表示相交的路径个数,(也可以看做选择的终点序列的逆序对个数)

    按照每个起点选择每一个终点构造出一个组合数的矩阵,按照矩阵的的定义答案就是这个矩阵的行列式

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+7;
    const ll mod=1000000007;
    int inv[maxn],e[107],s[107],fac[maxn];
    ll a[107][107];
    
    ll det(int n) {
        ll ans=1;
        int k=0;
        for(int i=0;i<n;i++) {
            for(int j=i+1;j<n;j++) {
                int x=i,y=j;
                while(a[y][i]) {
                    ll t=a[x][i]/a[y][i];
                    for(int l=i;l<n;l++) a[x][l]=(a[x][l]-a[y][l]*t)%mod;
                    swap(x,y);
                }
                if(x!=i) {
                    for(int l=0;l<n;l++) swap(a[i][l],a[x][l]);
                    k^=1;
                }
            }
            if(a[i][i]==0) return 0;
            else ans=ans*a[i][i]%mod;
        }
        if(k) ans=-ans;
        return (ans+mod)%mod;
    }
    void init() {
        inv[0]=inv[1]=1;
        fac[0]=fac[1]=1;
        for(int i=2;i<maxn;i++) {
            fac[i]=1ll*fac[i-1]*i%mod,
            inv[i]=1ll*inv[mod%i]*(mod-mod/i)%mod;
        }
        for(int i=2;i<maxn;i++) inv[i]=1ll*inv[i-1]*inv[i]%mod;
    }
    ll C(ll n,ll m) {
        if(m<0) return 0;
        return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;
    }
    int main( ) {
        int t;
        cin>>t;
        init();
        while(t--) {
            int n,k;
            cin>>n>>k;
            for(int i=0;i<k;i++) cin>>s[i];
            for(int i=0;i<k;i++) cin>>e[i];
            for(int i=0;i<k;i++) {
                for(int j=0;j<k;j++) {
                    a[i][j]=C(n-1+e[j]-s[i],e[j]-s[i]);
                }
            }
            cout<<det(k)<<endl;
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Entity SQL 初入
    ObjectQuery查询及方法
    Entity Framework 的事务 DbTransaction
    Construct Binary Tree from Preorder and Inorder Traversal
    Reverse Linked List
    Best Time to Buy and Sell Stock
    Remove Duplicates from Sorted Array II
    Reverse Integer
    Implement Stack using Queues
    C++中const限定符的应用
  • 原文地址:https://www.cnblogs.com/iwomeng/p/11623714.html
Copyright © 2011-2022 走看看