HDU5852 Intersection is not allowed!

拖了100年的题目

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. 

InputThe 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). 
OutputPrint 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

这个题目一看到还是晕了,但是每个点好像很有规律的啊,可以容斥的

LGV了解一下

然后就是处理出行列式,计算行列式的值了

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MD=1e9+7;
const int N=2e5+5,M=105;
int s[M],e[M];
ll a[M][M];
ll det(int n)
{
    ll ans=1;
    int sign=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 k=i; k<n; k++)
                    a[x][k]=(a[x][k]-a[y][k]*t)%MD;
                swap(x,y);
            }
            if(x!=i)
            {
                for(int k=0; k<n; k++)swap(a[i][k],a[x][k]);
                sign^=1;
            }
        }
        if(a[i][i]==0)return 0;
        else ans=ans*a[i][i]%MD;

    }
    if(sign)ans=-ans;
    ans=(ans+MD)%MD;
    return ans;
}
int fac[N],inv[N];
ll C(ll n,ll m)
{
    if(m<0)return 0;
    return 1LL*fac[n]*inv[m]%MD*inv[n-m]%MD;
}
int main()
{
    inv[0]=inv[1]=fac[0]=fac[1]=1;
    for(int i=2; i<N; i++) fac[i]=1LL*fac[i-1]*i%MD,inv[i]=1LL*inv[MD%i]*(MD-MD/i)%MD;
    for(int i=2; i<N; i++) inv[i]=1LL*inv[i-1]*inv[i]%MD;
    int n,k,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&k);
        for(int i=0; i<k; i++)scanf("%d",&s[i]);
        for(int i=0; i<k; i++)scanf("%d",&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]);
        printf("%lld\n",det(k));
    }
}

从(1,1)到(n,m)两条互不相交的路径条数C(n+m-4, n-2)^2-C(n+m-4,n-1)^2

简化为从(1,2)到(n-1,m)从(2,1)到(n,m-1)两条路径

posted @ 2018-10-09 16:35  暴力都不会的蒟蒻  阅读(241)  评论(0编辑  收藏  举报