ZOJ 3791 An easy game DP+组合数
给定两个01序列,每次操作可以任意改变其中的m个数字 0变 1 1 变 0,正好要变化k次,问有多少种变法
dp模型为dp[i][j],表示进行到第i次变化,A,B序列有j个不同的 变法总和。
循环k次,每次针对m,向那j个不同 分1-j个即可,不过要用到组合数,因为对每个数操作不同都不一样
最后结果就是 dp[k][0]
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL long long using namespace std; LL dp[110][110]; LL c[110][110]; int n,m,k,len; char s1[110],s2[110]; const LL M=1000000000+9; void init() { c[0][0]=1; for (int i=1;i<110;i++){ c[i][0]=1; for (int j=1;j<=i;j++){ c[i][j]=c[i-1][j-1]+c[i-1][j]; c[i][j]%=M; } } } int main() { init(); while (scanf("%d%d%d",&n,&k,&m)!=EOF) { scanf("%s%s",s1,s2); int a=0; for (int i=0;i<n;i++){ if (s1[i]!=s2[i]){ a++; } } memset(dp,0,sizeof dp); dp[0][a]=1; for (int i=0;i<k;i++){ for (int j=0;j<=n;j++){ if (dp[i][j]){ for (int q=0;q<=min(m,j);q++){ int sta=j+m-2*q; dp[i+1][sta]+=c[j][q]*c[n-j][m-q]%M*dp[i][j]%M; if (dp[i+1][sta]>=M) dp[i+1][sta]%=M; } } } } printf("%lld\n",dp[k][0]); } return 0; }