题目链接:https://vjudge.net/problem/HDU-6391
思路:转载自https://blog.csdn.net/qq_34454069/article/details/81669398
AC代码:
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
#define mod 19260817
using ll=long long;
ll dp[43][23][43];//n个数字,k次选择,m次为1
ll n,k;
ll fac[43];
ll ifac[43];
ll inv[43];
long long quick_pow(long long a,long long t)
{
long long ans=1;
while(t)
{
if(t&1)
ans=ans*a%mod;
a=a*a%mod;
t=t/2;
}
return ans;
}
void init()
{
fac[0]=fac[1]=1;
for(int i=2;i<=40;++i)
fac[i]=i*fac[i-1]%mod;
ifac[40]=quick_pow(fac[40],mod-2);
for(int i=39;i>=0;--i)
ifac[i]=ifac[i+1]*(i+1)%mod;
inv[0]=inv[1]=1;
for(int i=2;i<=40;++i)
inv[i]=(mod-mod/i)*inv[mod%i]%mod;
}
long long C(int x,int y)
{
if(x<y)
return 0;
return fac[x]*ifac[y]%mod*ifac[x-y]%mod;
}
int main()
{
init();
for(int i=1;i<=40;++i)
{
dp[i][0][0]=1;
for(int j=1;j<=min((long long)20,C(i,3));++j)
{
for(int k=0;k<=i;++k)
{
if(k-3>=0) dp[i][j][k]=(dp[i][j-1][k-3]*C(i-k+3,3)%mod+dp[i][j][k])%mod;
if(k-1>=0) dp[i][j][k]=(dp[i][j-1][k-1]*C(i-k+1,2)%mod*C(k-1,1)%mod+dp[i][j][k])%mod;
if(k+3<=i) dp[i][j][k]=(dp[i][j-1][k+3]*C(k+3,3)%mod+dp[i][j][k])%mod;
if(k+1<=i) dp[i][j][k]=(dp[i][j-1][k+1]*C(k+1,2)%mod*C(i-k-1,1)%mod+dp[i][j][k])%mod;
if(j-2>=0) dp[i][j][k]=(dp[i][j][k]+mod-(dp[i][j-2][k]*(j-1)%mod*(C(i,3)-j+2))%mod)%mod;
}
}
}
int ca=1;
while(scanf("%d %d",&n,&k)&&(n||k))
{
char str1[43];
char str2[43];
scanf("%s",str1);
scanf("%s",str2);
int m=0;
for(int i=0;i<n;++i)
m+=(str1[i]-'0')^(str2[i]-'0');
cout<<"Case #"<<ca++<<": ";
cout<<dp[n][k][m]*quick_pow(C(n,m),mod-2)%mod*ifac[k]%mod<<endl;
}
return 0;
}