NewCoder 多校1 A Monotonic Matrix (组合数学)

题目链接:https://www.nowcoder.com/acm/contest/139/A

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define read(x,y) scanf("%d%d",&x,&y)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
const int  maxn =2e3+5;
const int mod=1e9+7;
const ll INF =1e18+7;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:要求用0,1,2三种数字填满一个给定的n*m的矩阵的方案数,
要求Mij<=Mi(j+1),Mij<=M(i+1)j。

首先要知道不相交路径的相关知识,
以及其理论基础,在网格图中,a1,a2,...an到b1,b2,...bn的不相交路径数量,
是行列式,det|e(i,j)| i:1~n,j:1~m。
这题不难想到,0,1和1,2分别代表两种路径,
但单纯的用组合数相乘会发现有重复,
所以稍微思维转换下,把其中的一类路径统一平移,斜对角平移一格,
然后求这两对点的不相交路径数量。

至此,,问题就变的很简单了,组合数搞一下就行。

*/
///组合数和逆元
ll fac[maxn],inv[maxn];
void init()
{
    fac[0]=1;for(int i=1;i<maxn;i++) fac[i]=fac[i-1]*i%mod;
    inv[maxn-1]=powmod(fac[maxn-1],mod-2);
    for(int i=maxn-2;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
}
ll C(ll n,ll m){return fac[n]*inv[m]%mod*inv[n-m]%mod;}

ll n,m;
int main()
{
    init();
    while(scanf("%lld%lld",&n,&m)!=EOF)
        printf("%lld\n",(C(n+m,m)*C(n+m,m)%mod-C(n+m,n-1)*C(n+m,n+1)%mod+mod)%mod);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37451344/article/details/82916639