CodeForces 37d

来源:互联网 发布:vb.net和c#区别 编辑:程序博客网 时间:2024/06/08 06:26

一排有m个房子从1到m,每个房子现在有xi人,每个房子最多能做小yi个人,
现在所有人开始移动,每个人只能向后面的房子移动,
问有多少种方案

#include<cstdio>#include<iostream>#include<cstring>using namespace std;const int N=1100;const int mod=1e9+7;const int INF=0x3f3f3f3f;typedef __int64 LL;LL jie[N],inv[N];LL _pow(LL a,int b){    LL c=1;    while(b){        if(b&1){            c*=a;c%=mod;        }        a*=a;a%=mod;b/=2;    }    return c;}void init(){    jie[0]=inv[0]=1;    int n=1000;    for(int i=1;i<=n;i++){        jie[i]=jie[i-1]*i%mod;    }    for(int i=n;i>=1;i--){        if(i==n)inv[i]=_pow(jie[i],mod-2);        else {            inv[i]=inv[i+1]*(i+1)%mod;        }    }}LL C(int i,int j){    if(i<j)return 0;    return jie[i]*inv[j]%mod*inv[i-j]%mod;}int xx[N],yy[N];int sum,s[N];LL dp[N][N];int vis[N][N];int main(){    #ifdef DouBi    freopen("in.cpp","r",stdin);    #endif // DouBi    int m;    init();//    printf("%I64d\n",C(3,1));    while(scanf("%d",&m)!=EOF){        sum=0;        for(int i=0;i<m;i++){            scanf("%d",&xx[i]);            sum+=xx[i];            s[i]=xx[i];            if(i)s[i]+=s[i-1];        }        for(int i=0;i<m;i++){            scanf("%d",&yy[i]);        }        memset(dp,0,sizeof(dp));        memset(vis,0,sizeof(vis));        for(int i=0;i<m;i++){            for(int j=0;j<=s[i];j++){                for(int k=0;k<=yy[i]&&k<=j;k++)if(i==0&&j-k==0||i&&vis[i-1][j-k]){                    vis[i][j]=1;                    LL x=C(s[i]-(j-k),k);                    if(i)x*=dp[i-1][j-k];                    x%=mod;                    dp[i][j]+=x;                    dp[i][j]%=mod;                }            }        }        LL ans=dp[m-1][sum];        for(int i=0;i<m;i++){            if(i)ans*=C(sum-s[i-1],xx[i]);            else ans*=C(sum,xx[i]);            ans%=mod;        }        printf("%I64d\n",ans);    }    return 0;}
0 0