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:

/*************************************************************************
	> File Name: malasongN.cpp
	> Author: Hcacai
	> Created Time: 2019 Friday, July 26, 2003, 1343 minutes 18 seconds
 ************************************************************************/

#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)     //When n<m, i can take up to n
		{
			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                  //Otherwise i can take up to m-1
		{
		     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++)  // n<m && n>=m
		{
			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