HDU6143 Killer Names(DP and Repulsion Principles)
Title: m characters make up two names and words of n length respectively. It is required that the names and words cannot have the same characters. How many possibilities are there
1. The rejection principle: for names we select I characters (which are used for all I characters); for words we select all the remaining characters (which are used for any of them); for the number of words we use a fast power modulus; for names we define the f function, f[i] means only I letters, f[i]=i^n-f[i-1]*C (i, i-i)1) -f[i-2]*C(i, i-2)...-f[1]*C(i,1);
So the final result is i=1m_1C(m,i) f[i](m_i)n\sum_{i=1}^{m-1}C(m,i)*f[i]*(m-i)^n_i=1m_1 C(m,i)f[i](m_i)n
Code:
#include<bits/stdc++.h>
#include<cstdio>
const int mod=1e9+7;
typedef long long ll;
ll C[2006][2006];
ll f[2005];
using namespace std;
void Cnm()
{
int len=2005;
C[1][1]=1;
for(int i=2; i<len; i++)
{
C[i][1]=i;
for(int j=2 ; j<=i; j++)
{
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
}
}
}
ll quick_pow_mod(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 fi(ll n)
{
f[1]=1;
for(int i=2; i<=n; i++)
{
ll temp=0;
for(int j=1; j<i; j++)
{
temp=(temp+C[i][j]*f[j]%mod)%mod;
}
f[i]=(quick_pow_mod(i, n)+mod-temp)%mod;
}
}
int main()
{
Cnm();
int T;
scanf("%d", &T);
while(T--)
{
ll n,m,ans;
scanf("%lld%lld", &n,&m);
fi(n);
if(n<m)
{
ans=0;
for(int i=1; i<=n; i++)
{
ans=(ans+C[m][i]*f[i]%mod*quick_pow_mod(m-i,n)%mod)%mod;
}
}
else
{
ans=0;
for(int i=1; i<=m-1; i++)
{
ans=(ans+C[m][i]*f[i]%mod*quick_pow_mod(m-i, n)%mod)%mod;
}
}
printf("%lld\n", ans);
}
return 0;
}
Idea 2:dp, dp[i][j] denotes the possibility of using J characters for length i, recursive equation:
dp[i][j]=dp[i-1][j-1]*(m-j+1)+dp[i-1][j]*j
Code:
#include<bits/stdc++.h>
#include<cstdio>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll dp[2005][2005];
ll quick_mod(ll a,ll b)
{
ll res=1;
while(b)
{
if(b&1) res=(res*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return res;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n,m;
ll ans=0;
scanf("%d%d", &n, &m);
dp[1][1]=m;
for(int i=2; i<=n; i++)
{
for(int j=1; j<=i && j<m; j++)
{
dp[i][j]=(dp[i-1][j]*j%mod+dp[i-1][j-1]*(m-j+1)%mod)%mod;
}
}
for(int i=1; i<m; i++)
{
ans=(ans+dp[n][i]*quick_mod(m-i,n)%mod)%mod;
}
printf("%lld\n", ans);
}
return 0;
}
Posted by sxiix on Tue, 30 Jul 2019 11:14:00 -0700