JZOJ 1667【AHOI2009】中国象棋——dp
题目:https://jzoj.net/senior/#main/show/1667
只注重0、1、2的列有多少个,不注重它们的位置,就能记录了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const int N=105,mod=9999973; int n,m,dp[2][N][N][N],ans,jc[N],jcn[N]; int pw(int x,int k) { int ret=1;while(k){if(k&1)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=1;}return ret; } void init() { jc[0]=1; for(int i=1;i<=m;i++)jc[i]=(ll)jc[i-1]*i%mod;/////m not n jcn[m]=pw(jc[m],mod-2); for(int i=m-1;i>=0;i--)jcn[i]=(ll)jcn[i+1]*(i+1)%mod; } int C(int n,int m) { return (ll)jc[n]*jcn[m]%mod*jcn[n-m]%mod; } int main() { scanf("%d%d",&n,&m);dp[0][m][0][0]=1; init(); for(int i=1;i<=n;i++) { int d=(i&1); for(int x=0;x<=m;x++) for(int y=0;y<=m;y++) { int z=m-x-y; dp[d][x][y][z]=dp[!d][x][y][z]; if(y)(dp[d][x][y][z]+=(ll)dp[!d][x+1][y-1][z]*(x+1)%mod)%=mod;//0->1 if(z)(dp[d][x][y][z]+=(ll)dp[!d][x][y+1][z-1]*(y+1)%mod)%=mod;//1->2 if(y>1)(dp[d][x][y][z]+=(ll)dp[!d][x+2][y-2][z]*C(x+2,2)%mod)%=mod;//0,0->1,1 if(y&&z)(dp[d][x][y][z]+=(ll)dp[!d][x+1][y][z-1]*(x+1)%mod*y%mod)%=mod;//0,1->1,2 if(z>1)(dp[d][x][y][z]+=(ll)dp[!d][x][y+2][z-2]*C(y+2,2)%mod)%=mod;//1,1->2,2 } } int d=(n&1); for(int x=0;x<=m;x++) for(int y=0;y<=m;y++) (ans+=dp[d][x][y][m-x-y])%=mod; printf("%d\n",ans); return 0; }