给出两个等长的字符串,每次需要改变m个数字,每次必须改变k个数字,求从第一个串变化到第二个串的方案数。
DP。f[i][j]改变i步后,有j个位置被改变的方案数。然后直接枚举当前改变的几个位置是前面重合的。
然后统计答案输出即可。
#include <iostream> #include <cstring> #include <cstdio> #define M 1000000009 #define maxn 105 typedef long long ll; using namespace std; ll C[maxn][maxn]; ll f[maxn][maxn]; int n,k,m,change; ll ans; ll power(ll A,ll B) { ll tot=1; while (B){ if (B&1) tot=tot*A%M; A=A*A%M,B>>=1; } return tot; } void _init() { memset(C,0,sizeof C); C[0][0]=1; for (int i=1; i<maxn; i++){ C[i][0]=1; for (int j=1; j<=i; j++) C[i][j]=(C[i-1][j]+C[i-1][j-1])%M; } } int main() { _init(); char s1[maxn],s2[maxn]; while (scanf("%d%d%d",&n,&k,&m)!=EOF){ change=0; scanf("%s%s",s1,s2); for (int i=0; i<n; i++) if (s1[i]!=s2[i]) change++; memset(f,0,sizeof f); f[0][0]=1; for (int i=0; i<k; i++)//after the ith time of changes for (int j=0; j<=n; j++){//the number of 1 is j if (f[i][j]==0) continue; for (int x=max(0,j+m-n); x<=min(j,m); x++){ f[i+1][j-x+m-x]+=f[i][j]*(C[j][x]*C[n-j][m-x]%M)%M; f[i+1][j-x+m-x]%=M; } } ans=f[k][change]*power(C[n][change],M-2)%M; printf("%d ",(int)ans); } return 0; }