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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

HDU.5909.Tree Cutting(树形DP FWT/点分治)

發布時間:2024/8/26 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 HDU.5909.Tree Cutting(树形DP FWT/点分治) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接

\(Description\)

給定一棵樹,每個點有權值,在\([0,m-1]\)之間。求異或和為\(0,1,...,m-1\)的非空連通塊各有多少個。
\(n\leq 1000,m\leq 2^{10}\)

\(Solution\)

在每個連通塊的根節點處統計。\(f[x][k]\)表示以\(x\)為根,異或和為\(k\)的連通塊(子樹)有多少個。
那么\(f[x][k]=f[x][k]+\sum_{i\ \mathbb{xor}\ j=k}f[x][i]*f[v][j],\ v=son[x]\)
后一部分就是異或卷積,可以用\(FWT\)優化。

具體實現,不需要每次轉移一棵子樹都\(FWT,IFWT\)一次。中間過程一直用\(FWT\)后的\(f\)計算就可以了。
可能有的問題是,\(f\)本身(\(f[x][k]\))還要加上自己,必須在轉移的時候\(IFWT\)回去?不妨在\(f[v]\)計算完之后\(IFWT(f[v])\),令\(f[v][0]++\),然后再\(FWT\)回去,用這個\(f[v]\)去更新\(f[x]\)。這樣就可以直接用\(FWT\)后的\(f\)計算了。
\(f[x][0]\)在計算前是不能\(+1\)的,因為必須要求\(f[x]\)代表的非空連通塊是以\(x\)為根的。
最后把所有\(f[i]\ IFWT\)回去,再令\(f[i][0]\)--。
復雜度\(O(nm\log m)\)

所以有這兩種寫法的差異。。
https://www.cnblogs.com/cjyyb/p/9065611.html
https://blog.csdn.net/clover_hxy/article/details/72722352
還可以點分治。。在第二篇里有。不想寫了。

//858MS 5528K(怎么那么多跑的很快的啊--點分?) #include <cstdio> #include <cctype> #include <cstring> #include <algorithm> //#define gc() getchar() #define MAXIN 200000 #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) #define inv2 500000004 #define mod 1000000007 #define Add(x,y) (x+y>=mod?x+y-mod:x+y) #define Sub(x,y) (x<y?x-y+mod:x-y) typedef long long LL; const int N=1024+5;int lim,Enum,H[N],nxt[N<<1],to[N<<1],f[1005][N]; char IN[MAXIN],*SS=IN,*TT=IN;inline int read() {int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-'0',c=gc());return now; } inline void AE(int u,int v) {to[++Enum]=v, nxt[Enum]=H[u], H[u]=Enum;to[++Enum]=u, nxt[Enum]=H[v], H[v]=Enum; } void FWT(int *a,int lim,int opt) {for(int i=2; i<=lim; i<<=1)for(int j=0,mid=i>>1; j<lim; j+=i)for(int k=j; k<j+mid; ++k){int x=a[k], y=a[k+mid];a[k]=Add(x,y), a[k+mid]=Sub(x,y);if(opt==-1) a[k]=1ll*a[k]*inv2%mod, a[k+mid]=1ll*a[k+mid]*inv2%mod;} } void DFS(int x,int fa) {FWT(f[x],lim,1);for(int i=H[x],v; i; i=nxt[i])if((v=to[i])!=fa){DFS(v,x);for(int j=0; j<lim; ++j) f[x][j]=1ll*f[x][j]*f[v][j]%mod;}FWT(f[x],lim,-1), f[x][0]=Add(f[x][0],1), FWT(f[x],lim,1); }int main() {static LL Ans[N];for(int T=read(); T--; ){Enum=0, memset(H,0,sizeof H);memset(f,0,sizeof f), memset(Ans,0,sizeof Ans);int n=read(),m=read(); lim=m;for(int i=1; i<=n; ++i) ++f[i][read()];for(int i=1; i<n; ++i) AE(read(),read());DFS(1,1);for(int i=1; i<=n; ++i){FWT(f[i],lim,-1), f[i][0]=Sub(f[i][0],1);for(int j=0; j<m; ++j) Ans[j]+=f[i][j];}for(int i=0; i<m; ++i) printf("%d%c",int(Ans[i]%mod)," \n"[i+1==m]);//輸出格式。。}return 0; }

轉載于:https://www.cnblogs.com/SovietPower/p/10027062.html

總結

以上是生活随笔為你收集整理的HDU.5909.Tree Cutting(树形DP FWT/点分治)的全部內容,希望文章能夠幫你解決所遇到的問題。

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