http://acm.hdu.edu.cn/showproblem.php?pid=6143
题意:有m种字符,要求构造两段长度为n的字符串,其中这两段不能有相同的字符
枚举左边选了i种字符,右边可以选1,2....min(n,m-i)种字符
这样就把问题转化为用k种字符构造n长度的字符串的种类有多少种
容斥:单独考虑每一位上的字符都有k种选择,k^n,但会有不够k种的情况,所以要减去只有k-1种颜色,只有k-2种颜色。。。。的情况
这里是用容斥处理一下
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mo = 1e9 + 7;
long long soo[2005];
long long myc[2005][2005];
long long poww(long long x,int t)
{
long long ans=1;
while(t)
{
if(t&1)
ans=(ans*x)%mo;
x=(x*x)%mo;
t>>=1;
}
return ans;
}
void init()
{
myc[0][0]=1;
myc[1][0]=myc[1][1]=1;
for(int i=2;i<=2000;i++)
{
myc[i][0]=1;
myc[i][i] = 1;
for(int j=1;j<i;j++)
myc[i][j]=(myc[i-1][j]+myc[i-1][j-1])%mo;
}
return ;
}
void initt(int n)
{
soo[1]=1;
for(int k=2;k<=n;k++)
{
soo[k]=poww(k,n);
for(int i=1;i<k;i++)
{
soo[k]=((soo[k]-(myc[k][k-i]*soo[i])%mo)%mo+mo)%mo;
}
}
}
int main()
{
int T,n,m,i,j;
cin>>T;
init();
while(T--)
{
cin>>n>>m;
initt(n);
long long ans=0;
for(i=1;i<=min(m-1,n);i++)
{
long long now=(myc[m][i]*soo[i])%mo;
int up=min(n,m-i);
for(j=1;j<=up;j++)
{
ans=(ans+now*((myc[m-i][j]*soo[j])%mo))%mo;
}
}
cout<<ans<<endl;
}
return 0;
}
更简单的做法是第二类斯特林数,第二类斯特林数是指将p个有序号的小球放入k个无区别的盒子里并保证每个盒子里有一个小球的方案数,给k个盒子加上区别(乘以A(k,k)) 其实也就相当于给小球染上k种不同的颜色,也就是题目所需要的
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mo = 1e9 + 7;
long long s[2005][2005],f[2005];
long long myc[2005][2005];
void init()
{
myc[0][0]=1;
myc[1][0]=myc[1][1]=1;
for(int i=2;i<=2000;i++)
{
myc[i][0]=1;
myc[i][i] = 1;
for(int j=1;j<i;j++)
myc[i][j]=(myc[i-1][j]+myc[i-1][j-1])%mo;//组合数
}
f[0]=1;
for(int i=1;i<=2000;i++)
f[i]=(f[i-1]*i)%mo;//阶乘
for(int i=0;i<=2000;i++)
s[i][i]=1,s[i][0]=0;
for(int i=1;i<=2000;i++)
{
for(int j=1;j<=i-1;j++)
{
s[i][j]=(j*s[i-1][j]+s[i-1][j-1])%mo;//斯特林数
}
}
return ;
}
int main()
{
int T,n,m,i,j;
cin>>T;
init();
while(T--)
{
cin>>n>>m;
long long ans=0;
for(i=1;i<=min(m-1,n);i++)
{
long long now=(((myc[m][i]*s[n][i])%mo)*f[i])%mo;
int up=min(n,m-i);
for(j=1;j<=up;j++)
{
ans=(ans+(f[j]*now)%mo*((myc[m-i][j]*s[n][j])%mo))%mo;
}
}
cout<<ans<<endl;
}
return 0;
}