关于 Lagrange Interpolation。
插值即是对于给出的向量组 ,其中 ,构造一个函数 使得 ,有 。
朴素做法即对方程组消元,。
Lagrange 插值则是选择了类 CRT 的构造方法,即构造 个函数 ,使得 ,有 ,,有 ,那么构造结果 。对于一个 ,我们有 ,此时若 ,则我们已经满足了条件二;考虑条件一,令 即可,即有 ,。
看回这个题,朴素的 dp 做法即是令 表示考虑子树 的方案数,满足 的赋权为 ,转移即各个子树的 dp 和的乘积,容易看出这是个多项式,即 是关于 的 次多项式,其中 为 的子树大小。考虑差分 ,又因为叶子结点满足条件即证。
那么求出 ,插值求出其曲线方程,带入 即可。
const int mod = 1e9+7;
il int sub(int x,int y) {
if ((x-=y)<0) x+=mod;
return x;
}
il int mul(int x,int y) {
return static_cast<long long>(x)*y%mod;
}
il void adds(int& x,int y) {
if ((x+=y)>=mod) x-=mod;
}
il void muls(int& x,int y) {
x=static_cast<long long>(x)*y%mod;
}
il int qpow(int x,int y) {
int z(1);
for (; y; y>>=1,muls(x,x))
if (y&1) muls(z,x);
return z;
}
il int inv(int m) {
assert(m>0);
return qpow(m,mod-2);
}
int n, dp[3<<10][3<<10], d, Y[3<<10];
bsi<int> adj[3<<10];
void dfs(int x) {
rep(i,1,n+1) dp[x][i] = 1;
for (auto y : adj[x]) {
dfs(y);
rep(i,1,n+1) muls(dp[x][i], dp[y][i]);
}
rep(i,1,n+1) adds(dp[x][i], dp[x][i-1]);
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
int x;
cin >> n >> d;
rep(i,1,n) {
cin >> x;
x--;
adj[x] += i;
}
dfs(0);
rep(i,n+1) Y[i] = dp[0][i];
int ans=0;
rep(i,n+1) {
int u=Y[i],v=1;
rep(j,n+1) if (i!=j) muls(u,sub(d,j)),muls(v,sub(i,j));
adds(ans,mul(u,inv(v)));
}
cout<<ans<<"\n";
}