传送门
二项式反演裸题
设
f
i
f_i
fi表示至多有
i
i
i种颜色的方案数,
g
i
g_i
gi为恰好有
i
i
i种颜色的方案数
这个是跟树的形态无关的因为一个点只有一个父亲,所以
f
i
=
i
×
(
i
−
1
)
n
−
1
f_i=i\times(i-1)^{n-1}
fi=i×(i−1)n−1
再套用公式
f
k
=
∑
i
=
0
k
C
k
i
×
g
i
f_k=\sum_{i=0}^k C_k^i\times g_i
fk=∑i=0kCki×gi
反演得到
g
k
=
∑
i
=
0
k
(
−
1
)
k
−
i
×
C
k
i
×
f
i
g_k=\sum_{i=0}^k (-1)^{k-i}\times C_k^i\times f_i
gk=∑i=0k(−1)k−i×Cki×fi
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 2505
#define LL long long
using namespace std;
template<class T>inline void rd(T &x){
x=0; short f=1; char c=getchar();
while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
x*=f;
}
int n,k,f[N],ans,C[N][N];
const int mod=1e9+7;
inline int qpow(int x,int k){
int ret=1;
while(k){
if(k&1) ret=1LL*ret*x%mod;
x=1LL*x*x%mod; k>>=1;
} return ret;
}
inline void prework(int n){
C[0][0]=1;
for(int i=1;i<=n;i++) C[i][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
}
int main(){
rd(n),rd(k); int x; prework(k);
for(int i=1;i<n;i++) rd(x);
for(int i=1;i<=k;i++) f[i]=1LL*i*qpow(i-1,n-1)%mod;
for(int i=0;i<=k;i++)
if((k-i)&1) (ans+=mod-1LL*f[i]*C[k][i]%mod)%=mod;
else (ans+=1LL*f[i]*C[k][i]%mod)%=mod;
printf("%d\n",ans);
return 0;
}