日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[CF995F] Cowmpany Cowmpensation(树形dp,拉格朗日插值)

發布時間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [CF995F] Cowmpany Cowmpensation(树形dp,拉格朗日插值) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

樹形DP:
f[u][i]f[u][i]f[u][i]表示給uuu的子樹分配工資,uuu點工資為iii的方案數
f[u][i]=∏v∈sonu(∑j=1if[v][j])f[u][i]=\prod\limits_{v\in son_u}(\sum\limits_{j=1}^{i}f[v][j])f[u][i]=vsonu??(j=1i?f[v][j])
前綴和優化:
g[u][i]=∑j=1if[u][j]g[u][i]=\sum\limits_{j=1}^{i}f[u][j]g[u][i]=j=1i?f[u][j]
f[u][i]=∏v∈sonug[v][i]f[u][i]=\prod\limits_{v\in son_u}g[v][i]f[u][i]=vsonu??g[v][i]
時間復雜度O(nd)O(nd)O(nd)
考慮用拉格朗日插值優化O(n2)O(n^2)O(n2)
gu(x)g_u(x)gu?(x)為關于xxx的函數,代入xxx,即可得到g[u][x]g[u][x]g[u][x]
合理猜想gu(x)g_u(x)gu?(x)的次數為szusz_uszu?uuu的子樹大小),可以用數學歸納法證明:

  • uuu 為葉子結點時,gu(x)=xg_u(x)=xgu?(x)=x,成立。
  • uuu 非葉子結點時,考慮:
    gu(x)?gu(x?1)=∏v∈sonugv(x)g_u(x)-g_u(x-1)=\prod\limits_{v\in son_u}g_v(x)gu?(x)?gu?(x?1)=vsonu??gv?(x)
    由于 vvv 滿足猜想,即gv(x)g_v(x)gv?(x) 的次數為 szvsz_vszv?,則 gu(x)?gu(x?1)g_u(x)-g_u(x-1)gu?(x)?gu?(x?1) 的次數為 ∑v∈sonuszv\sum\limits_{v\in son_u}sz_vvsonu??szv?,即 szu?1sz_u-1szu??1
    再還原差分,次數 +1,有 gu(x)g_u(x)gu?(x) 是關于 xxxszu?1+1=szusz_u-1+1=sz_uszu??1+1=szu? 次函數。

所以我們只要知道g1(1),g1(2),...,g1(n)g_1(1),g_1(2),...,g_1(n)g1?(1),g1?(2),...,g1?(n),便可以用拉格朗日插值得出g1(d)g_1(d)g1?(d)

#include<iostream> #include<cstdio> using namespace std; typedef long long ll; const int mod=1e9+7; const int N=3050; struct Edge{int v,nxt;}edge[N]; int n,cnt,head[N],fa[N]; int d,f[N][N],sum[N][N],inv[N],ans; int add(int a,int b){return a+b>=mod?a+b-mod:a+b;} int mul(int a,int b){return 1ll*a*b%mod;} void addedge(int u,int v){edge[++cnt].v=v;edge[cnt].nxt=head[u];head[u]=cnt; } void dfs(int u){for(int i=head[u];i;i=edge[i].nxt){int v=edge[i].v;dfs(v);for(int j=1;j<=min(n,d);j++)f[u][j]=mul(f[u][j],sum[v][j]);}for(int j=1;j<=min(n,d);j++) sum[u][j]=add(sum[u][j-1],f[u][j]); } int main(){scanf("%d%d",&n,&d);inv[1]=1;for(int i=2;i<=n;++i) inv[i]=mul(mod-mod/i,inv[mod%i]);for(int i=2;i<=n;i++){scanf("%d",&fa[i]);addedge(fa[i],i);}for(int i=1;i<=n;i++)for(int j=1;j<=min(n,d);j++) f[i][j]=1;dfs(1);if(d<=n) printf("%d\n",sum[1][d]);else{for(int i=1;i<=n;i++){int x=sum[1][i];for(int j=0;j<=n;++j) if(i^j) x=1ll*x*(d-j+mod)%mod*(i>j?inv[i-j]:mod-inv[j-i])%mod;ans=add(ans,x);}printf("%d\n",ans);}return 0; }

總結

以上是生活随笔為你收集整理的[CF995F] Cowmpany Cowmpensation(树形dp,拉格朗日插值)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。