【题解】Gym101933K King's Colors题解
\(\text{King's Colors}\)\({}^\texttt{Gym 101933K}\)题解
定义:\(f_i\) 表示使用了至多 \(i\) 种颜色的方案数;\(g_i\) 表示使用了恰好 \(i\) 种颜色的方案数。
那么 \(f_i=\displaystyle{ {m\choose i}\cdot \sum{i\choose j}\cdot g_j}\),\(f_i=\displaystyle {m\choose i}(i-1)^{n-1}i\)。
令 \(h_i=\displaystyle{\frac{f_i}{\displaystyle{m\choose i}}}=(i-1)^{n-1}i\)。\(\therefore h_i=\displaystyle{ \sum{i\choose j}\cdot g_j}\)。
令矩阵 \(A_{i,j}=\displaystyle {i\choose j}\),则 \(A^{-1}_{i,j}=\displaystyle {i\choose j}\times (-1)^{i-j}\)。
\(\because h=Ag \\\therefore g=A^{-1}h\\\therefore g_i=A_{i,j}^{-1}\times h_j=\displaystyle{i\choose j}\times (-1)^{i-j}\times (j-1)^{n-1}\times j\\\therefore g_{m}=\displaystyle{m\choose j}\times (-1)^{m-j}\times (j-1)^{n-1}\times j\)
Code
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
//#define int long long
namespace gtx{
// Fast IO
void read(int &x){
x = 0;int h = 1;char tmp;
do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
x*=h;
}
void read(char &x){do{x=getchar();}while(x==' '||x=='\n'||x=='\r');}
void write(char x){putchar(x);}
void write(int x){
if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
do st[++tot]=x%10,x/=10; while(x);
while(tot){putchar(st[tot--]+'0');}
}
void write(int x,char y){write(x);write(y);}
#ifndef int
void read(long long &x){
x = 0;int h = 1;char tmp;
do{tmp=getchar();if(tmp=='-')h*=-1;}while(!isdigit(tmp));
while(isdigit(tmp)) x*=10,x+=tmp-'0',tmp=getchar();
x*=h;
}
void write(long long x){
if(x<0) putchar('-'),x=-x;int st[200]={0},tot=0;
do st[++tot]=x%10,x/=10; while(x);
while(tot){putchar(st[tot--]+'0');}
}
void write(long long x,char y){write(x);write(y);}
#endif
const int MAXN = 2'500+10;
const int MOD = 1e9+7;
int n,m;
int qpow(int x,int y){
if(y<0) return qpow(qpow(x,-y),MOD-2);
long long now = x;
long long ans = 1;
while(y){
if(y&1){
ans *= now;ans%=MOD;
}
now *= now; now%=MOD;
y>>=1;
}
return ans;
}
int frac[MAXN],invfrac[MAXN];
int inv(int x){
return qpow(x,MOD-2);
}
int C(int n,int m){
return 1ll*frac[n]*invfrac[m]%MOD*invfrac[n-m]%MOD;
}
signed main(){
read(n);read(m);
frac[0] = invfrac[0] = 1;
for(int i = 1;i<=n;i++){
frac[i] = 1ll*frac[i-1]*i%MOD;
invfrac[i] = inv(frac[i]);
}
int ans = 0;
for(int j = 2;j<=m;j++){
ans += 1ll*C(m,j)*((m-j)&1?-1:1)%MOD*qpow(j-1,n-1)%MOD*j%MOD;
ans %= MOD;
}
write((ans%MOD+MOD)%MOD);
return 0;
}
}
signed main(){
// freopen(".in","r",stdin);
// freopen(".out","w",stdout);
// ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int T = 1;
// gtx::read(T);
while(T--) gtx::main();
return 0;
}