意甲冠军:给定两个01弦s1,s2.每一个变化s1在m字 - 位。要求k制作步骤之后s1变s2有多少种方法。
解法:DP,关键是状态的设计。考虑还是唯一性和可传递性。dp[i][j]表示第i步后有j个不同到目标的走法数。记忆化搜索dp[0][dif](dif表示初始时不同字符的个数)。
转移时候枚举选择情况就可以。
代码:
/******************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;
#define eps 1e-8
const double pi=acos(-1.0);
typedef long long LL;
const int Max=110;
const int INF=1000000009;
int n,k,m;
string s1,s2;
LL C[Max][Max];
int init()
{
for(int i=0; i<Max; i++)
for(int j=0; j<=i; j++)
C[i][j]=j?(C[i-1][j-1]+C[i-1][j])%INF:1;
}
LL dp[Max][Max];
int dif;
LL dfs(int step,int num)
{
if(dp[step][num]!=-1)
return dp[step][num];
LL ans=0;
for(int i=0; i<=num; i++)
{
if(i+n-num<m)
continue;
if(i>m)
break;
ans=(ans+(C[num][i]*C[n-num][m-i])%INF*dfs(step+1,num-i+m-i))%INF;
}
return dp[step][num]=ans;
}
int main()
{
init();
while(scanf("%d%d%d",&n,&k,&m)==3)
{
dif=0;
memset(dp,-1,sizeof dp);
cin>>s1>>s2;
for(int i=0; i<n; i++)
if(s1[i]!=s2[i])
dif++;
dp[k][0]=1;
for(int i=1;i<=n;i++)
dp[k][i]=0;
cout<<dfs(0,dif)<<'\n';
}
return 0;
}