题目:点击打开链接
题意:一个人的名字有名和姓,名和姓上各有n个字符位置,每个位置的字符从m个字符里面选择。问你有多少个人的名字其名和姓上没有相同的字符
解题思路:点击打开链接 这个解释的还是很好的额
#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll 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;
}
ll c[2005][2005];
void init()//组合数
{
for(int i=0; i<=2000; i++)
{
for(int j=0; j<=i; j++)
{
if(j==0 || j==i) c[i][j]=1;
else c[i][j] = (c[i-1][j-1]+c[i-1][j])%mod;
}
}
}
int f[2005];
int main()
{
int T;
scanf("%d",&T);
int n,m;
init();
while(T--)
{
scanf("%d%d",&n,&m);
if(m==1)
printf("0\n");
else
{
memset(f,0,sizeof(f));
ll ans=pow_mod(m-1,n)*c[m][1]%mod;
f[1]=1;
for(int i=2; i<=min(m,n); i++)
{
ll res=(c[m][i]*pow_mod(m-i,n))%mod;
ll tmp=0;
for(int j=1; j<=i; j++)
{
tmp=((c[i][j]*f[j])%mod+tmp)%mod;
}
f[i]=pow_mod(i,n)-tmp;
res=(res*f[i])%mod;
ans=(ans+res)%mod;
}
printf("%lld\n",ans);
}
}
return 0;
}