zoj 3791

给出两个01字符串s1,s2.每次改变s1上m个位置的字符。问k步之后使得s1变为s2的方法有多少种。

dp[i][j]  :第i步,不同为j的方案数。


typedef long long LL  ;

const  LL mod = 1000000009LL ;
LL   c[108][108] ;
void GetC(){
     c[0][0] = 1 ;
     for(int i = 1 ; i < 108 ; i++){
         c[i][0] = c[i][i] = 1 ;
         for(int j = 1 ; j < i ; j++){
             c[i][j] = (c[i-1][j] + c[i-1][j-1]) % mod ;
         }
     }
}

char s1[108]  , s2[108]  ;
int  n , m , k ;
LL   dp[108][108] ;
LL   DP(){
     int i , j , s  , d = 0  , t ;
     for(i = 0 ; i < n ; i++) d += (s1[i]!=s2[i]) ;
     memset(dp , 0 , sizeof(dp)) ;
     dp[0][d] = 1 ;
     for(i = 1 ; i <= k ; i++){
        for(j = 0 ; j <= n ; j++){
            for(t = 0 ; t <= min(m , j) ;  t++){
                 dp[i][j-t+m-t] += dp[i-1][j] * c[j][t] % mod * c[n-j][m-t] % mod ;
                 dp[i][j-t+m-t] %= mod ;
            }
        }
     }
     return dp[k][0] ;
}

int  main(){
     GetC() ;
     while(scanf("%d%d%d" ,&n ,&k ,&m) != EOF){
          scanf("%s%s" ,s1 , s2) ;
          printf("%lld\n" , DP()) ;
     }
     return 0  ;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值