[51nod 1362]搬箱子

来源:互联网 发布:淘宝网店赚钱 编辑:程序博客网 时间:2024/05/18 18:42

题目描述

有一个n*m的棋盘,左上角为(0,0),右下角为(n,m).在左上角有一个箱子(箱子是放在交叉点上的)。现在要把箱子搬到最后一排。搬的时候只有向右,向下,或者向右下方走一步。也就是说,假如箱子在(x,y),那么下一步只能把他搬到(x+1,y)或(x,y+1)或(x+1,y+1).
问有多少种的走法可以把箱子从左上角搬到最后一排。由于数目巨大,对X取余输出即可。

题目大意

考虑走到(n,j)的方案数?
枚举i表示斜走的步数,可以推出个组合数公式。
要对不同j求和。
套入下面这个式子就很简单了:
mi=0Cin=Cm+1n+1
组合数因为最后拆出来项数不多,也是可以算的
详见代码

#include<cstdio>#include<algorithm>#include<cmath>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;typedef long long ll;const int maxn=800+10;int p[30];int num[maxn*2][30],sum[maxn][30],f[maxn],g[maxn*2];int i,j,k,l,t,n,m,mo,top,ans,xx,yy;int quicksortmi(int x,int y){    if (!y) return 1;    int t=quicksortmi(x,y/2);    t=(ll)t*t%mo;    if (y%2) t=(ll)t*x%mo;    return t;}void gcd(int a,int b){    if (!b){        xx=1;yy=0;        return;    }    gcd(b,a%b);    int x=yy,y=xx-a/b*yy;    xx=x;yy=y;}int getny(int x){    gcd(x,mo);    return (xx%mo+mo)%mo;}int main(){    scanf("%d%d%d",&n,&m,&mo);    //if (n>m) swap(n,m);    k=mo;    t=floor(sqrt(mo));    fo(i,2,t)        if (k%i==0){            p[++top]=i;            while (k%i==0) k/=i;        }    if (k>1) p[++top]=k;    fo(j,1,top){        t=p[j];        fo(i,1,n+1){            k=i;            while (k%t==0){                sum[i][j]++;                k/=t;            }            sum[i][j]+=sum[i-1][j];        }    }    f[0]=1;    fo(i,1,n+1){        k=i;        fo(j,1,top){            t=p[j];            while (k%t==0) k/=t;        }        f[i]=(ll)f[i-1]*k%mo;    }    fo(j,1,top){        t=p[j];        fd(i,n+m+1,max(m-n+1,1)){            k=i;            while (k%t==0){                num[n+m-i+2][j]++;                k/=t;            }            num[n+m-i+2][j]+=num[n+m-i+1][j];        }    }    g[0]=1;    fd(i,n+m+1,max(m-n+1,1)){        k=i;        fo(j,1,top){            t=p[j];            while (k%t==0) k/=t;        }        g[n+m-i+2]=(ll)g[n+m-i+1]*k%mo;    }    fo(i,0,min(n,m)){        t=(ll)g[n+m-(m-i+1)+2]*getny(g[n+m-(n+m-i)])%mo*f[n]%mo;        t=(ll)t*getny(f[i])%mo*getny(f[n-i])%mo*getny(f[n+1])%mo;        fo(j,1,top){            k=num[n+m-(m-i+1)+2][j]-num[n+m-(n+m-i)][j];            k+=sum[n][j];            k-=sum[i][j];            k-=sum[n-i][j];            k-=sum[n+1][j];            t=(ll)t*quicksortmi(p[j],k)%mo;        }        (ans+=t)%=mo;    }    //fo(i,1,n) ans=(ll)ans*i%mo;    printf("%d\n",ans);}
0 0
原创粉丝点击