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
  • 相关阅读:
    Vue常用特性-表单基本操作和表单修饰符
    Tab选项卡
    Vue模板语法
    Vue基本使用
    Vue概述
    Express框架
    模板引擎artTemplate
    MongoDB增删改查操作
    数据库概述及环境搭建
    请求响应原理及HTTP协议
  • 原文地址:https://www.cnblogs.com/iwomeng/p/11623714.html
Copyright © 2011-2022 走看看