f(n,m)=n长度,恰好使用了m种字母的方案数
f(n,m)=mn−∑m−1i=1[Cimf(n,m−i)]
考虑name1使用了i种字母,name2使用了j种字母
则有f(n,i)∗f(n,j)∗Cim∗Cjm−i种方案
枚举i,j 则ans=∑i>0,j>0,i+j>0[f(n,i)∗f(n,j)∗Cim∗Cjm−i]
#include<stdio.h>
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define MEM(a,x) memset(a,x,sizeof(a))
#define lowbit(x) ((x)&-(x))
using namespace std;
const int inf=1e9+7;
const int N = 2000 + 5;
ll c[N][N];
ll C(ll n,ll m){
if(n<m){
return 0;
}
if(n==m||m==0){
return 1;
}
if(c[n][m]!=-1){
return c[n][m];
}
return (c[n][m]=(C(n-1,m-1)+C(n-1,m))%inf);
}
ll qPow(ll a,ll n){
ll ans=1;
ll t=a%inf;
while(n){
if(n&1){
ans=(ans*t)%inf;
}
t=(t*t)%inf;
n>>=1;
}
return ans;
}
ll f[N];
ll ff(int n,int m){
f[1]=1;
for(int i=2;i<=m;++i){
f[i]=qPow(i,n);
for(int j=1;j<i;++j){
f[i]=(f[i]-C(i,j)*f[i-j])%inf;
}
}
return f[m];
}
ll slove(int n,int m){
ff(n,m);
ll ans=0;
for(int a=0;a<=m;++a){
for(int b=0;a+b<=m;++b){
if(a+b==0){
continue;
}
ll t=(C(m,a)*f[a])%inf;
t=(t*C(m-a,b))%inf;
t=(t*f[b])%inf;
ans=(ans+t)%inf;
}
}
return (ans+inf)%inf;
}
int main()
{
//freopen("/home/lu/code/r.txt","r",stdin);
//freopen("/home/lu/code/w.txt","w",stdout);
int T;
scanf("%d",&T);
MEM(c,-1);
while(T--){
int n,m;
scanf("%d%d",&n,&m);
printf("%lld\n",slove(n,m));
}
return 0;
}