链接:http://acm.hdu.edu.cn/showproblem.php?pid=6391
题意:根据异或的性质,X_0⊕X_1⊕X_2⊕X_3⊕…..⊕X_(M-1)=S⊕T 计算出S⊕T中一共有cnt个1,将这个二进制数标准化, 使它成为前面N-cnt个0,后cnt个1的二进制数,答案保持不变,问题变为:用K个N位且有3个1的不同二进制数进行 异或,最终得到前面N-cnt个0,后面cnt个1这个二进制数,有多少种方案? 递推。设 表示用K个N位且有 3个1的不同二进制数进行异或,最终得到前面N-cnt个0,后面cnt个1这个二进制数的方案数。 递推方程: 此时得到的 未去除加入数字的先后顺序和加入重复串带来的影响 考虑加入重复串的影响, 表示去除加入i-2个数字并且后面有j个1这个二进制数但后来又异或上两 个之前没用过的相同的数的方案数, 考虑二进制数加入的先后顺序给答案带来的额外贡献, 即 ,其中 为数字i关于模mod的逆元
代码:
#pragma warning(disable:4996)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod =19260817;
bool flag = 0;
const int maxn = 45 + 6;
const int Maxn = 1e6 + 6;
char a[maxn], b[maxn];
ll dp[maxn][maxn];
int n, k;
int C[maxn][maxn];
ll qpow(ll a, ll b) {
ll res = 1;
while (b) {
if (b & 1)
res = res * a%mod;
a = a * a%mod;
b >>= 1;
}
return res;
}
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]) % mod;
}
}
}
ll solve() {
int res = 0;
for (int i = 0; i< n; i++) {
res += (a[i] != b[i]);
}
return res;
}
int main() {
int ca = 0;
init();
while (~scanf("%d%d", &n, &k), (n + k)) {
scanf("%s%s", a,b);
int cnt =solve();
dp[0][0] = 1;
ll fac = 1;
for (int i = 1; i <= k; i++) {
fac = fac * i%mod;
for (int j = 0; j <= n; j++) {
dp[i][j] = 0;
if(j>=3)dp[i][j] += dp[i - 1][j - 3] * C[n-(j-3)][3];
if(j>=1)dp[i][j] += dp[i - 1][j - 1] * C[n - (j - 1)][2] %mod* (j - 1);
if(j+1<=n)dp[i][j] += dp[i - 1][j + 1] * C[n - (j + 1)][1] %mod* C[j + 1][2];
if(j+3<=n)dp[i][j] += dp[i - 1][j + 3] * C[j + 3][3];
if(i>=2)dp[i][j] -= dp[i - 2][j] * (i - 1)%mod*(C[n][3] - (i - 2));
dp[i][j] %= mod;
}
}
ll ans = dp[k][cnt];
ans=ans*qpow(fac, mod - 2) % mod*qpow(C[n][cnt], mod - 2) % mod;
printf("Case #%d: %lld\n", ++ca, (ans+mod)%mod);
}
}