[gym101933]King's Colors 計數問題
阿新 • • 發佈:2018-12-16
/* [gym101933]King's Colors 樹上染色,一共k種顏色都要用到。相鄰節點顏色不同,問方案數。 */ #include<bits/stdc++.h> using namespace std; typedef long long ll; ll mod=1000000007; const int mmax=2555; const int nmax=2555; int n,k; /** 基礎加邊*/ int etot=0,to[mmax],nex[mmax],head[nmax]; void addedge(int u,int v){ to[++etot]=v,nex[etot]=head[u],head[u]=etot; } /** vir[i]: 使用i種顏色的方案數,包括小於等於k rea[i]:剛剛好使用i種顏色的方案數*/ ll vir[nmax],rea[nmax]; /** dfs:當前節點rt用1種顏色方案(一共k種顏色可選) dfs計算vir陣列。 vir[i]=dfs(0,i)*i; */ ll dfs(int rt,int k){ if(!head[rt])return 1; ll son_tot=1; for(int i=head[rt];i;i=nex[i]){ son_tot=son_tot*(k-1)%mod*dfs(to[i],k)%mod; //兒子節點除了當前節點選色其他k-1種顏色都能用。 } return son_tot; } /** 預處理計算i^(-1)%mod*/ ll ver[nmax]; ll quick_pow(ll a,ll x){ ll ans=1; while(x){ if(x&1) ans=ans*a%mod; a=a*a%mod; x>>=1; }return ans; } void init_ver(){ for(int i=1;i<=k;i++){ ver[i]=quick_pow(i,mod-2); } } int main(){ int pa; scanf("%d%d",&n,&k); for(int i=1;i<n;i++){ scanf("%d",&pa); addedge(pa,i); } init_ver(); for(int i=2;i<=k;i++){ vir[i]=i*dfs(0,i)%mod; rea[i]=vir[i]; ll C=i; for(int j=2;j<i;j++){ C=C*(i-j+1)%mod*ver[j]%mod; rea[i]=(rea[i]-C*rea[j]%mod+mod)%mod; //real[i]=vir[i]-sigma(2<=j<i)C(i,j)*real[j] } } printf("%I64d\n",rea[k]); return 0; }