题解:一般对于多种颜色染色(染色数很大>=1e8),并且染色的点很少的时候(点数<=3000)。设点数为1.可以先求出染色数(1~n+1)时所有的函数值,这样不管是对f()函数求和,还是非求和都能适用。然后套用拉格朗日差值的公式即可。f函数用dp预处理即可。
#include"bits/stdc++.h"
using namespace std;
typedef long long ll;
const int MX = 3006;
const int mod = 1e9+7;
int fa[MX];
ll dp[MX][MX],pre[MX],suf[MX];
ll fac[MX],inv[MX];
int n,D;
int sig(int x)
{
if(x&1) return mod-1;
return 1;
}
void prepare()
{
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++)
dp[i][j] = 1;
}
for(int i = n; i >= 1; i--){
for(int j = 1; j <= n; j++)
dp[i][j] = (dp[i][j]+dp[i][j-1])%mod;
for(int j = 1; j <= n; j++)
dp[fa[i]][j] = dp[fa[i]][j]*dp[i][j]%mod;
}
}
void init()
{
int n = 3003;
fac[0] = fac[1] = inv[0] = inv[1] = 1;
for(int i = 2; i <= n; i++){
fac[i] = fac[i-1]*i%mod;
inv[i] = (mod-mod/i)*inv[mod%i]%mod;
}
for(int i = 2; i <= n; i++)
inv[i] = inv[i-1]*inv[i]%mod;
}
void work(ll *d, int x)
{
pre[0] = suf[n+1] = 1;
for(int i = 1; i <= n; i++)
pre[i] = pre[i-1]*(x-i+mod)%mod;
for(int i = n; i >= 1; i--)
suf[i] = suf[i+1]*(x-i+mod)%mod;
ll ans = 0;
for(int i = 1; i <= n ; i++) {
ans += pre[i-1]*suf[i+1]%mod*d[i]%mod*inv[i-1]%mod*inv[n-i]%mod*sig(n-i)%mod;
ans = (ans%mod+mod)%mod;
}
printf("%lld\n",ans);
}
int main()
{
#ifdef LOCAL
freopen("input.txt","r",stdin);
#endif // LOCAL
init();
scanf("%d%d",&n,&D);
for(int i = 2; i <= n; i++){
scanf("%d",&fa[i]);
}
n += 2;
prepare();
work(dp[1],D);
return 0;
}