Question: Give You A tree. Each node of the tree has a weight value. The product of how many path weights you have is a full cube.
The title gives you k prime numbers (k <= 30). The ownership values can be divided into these K prime numbers.
Idea: the number of prime factors in a complete cube is a multiple of three, so we only need the number of prime numbers, and we only care about the remainder of the number to three.
Therefore, we can use a long integer to represent the number of prime factors from each node to the root (triple compression ). However, because bitwise operations are faster, I use a four-digit system, that is, each two represents the number of a prime factor.
When merging in the middle, calculate the number that is equal to 0 after the sum, and then use map for statistics.
Note: The pI value in the question cannot be obtained from 0 (how to deal with it for a long time? =)
# Include <stdio. h> # include <string. h ># include <map ># include <algorithm> # pragma comment (linker, "/Stack: 102400000,102400000") using namespace STD; # define maxn 50005 # define INF 0x3f3f3f _ int64 prime [35]; int N, K; struct tree {struct edge {int to, NEX; edge () {} edge (INT _ to, int _ NEX) {to = _ to; NEX = _ NEX;} edge [maxn * 2]; int head [maxn]; int index; void Init () {memset (Head,-1, size Of (head); Index = 0;} void add (int from, int to) {edge [Index] = edge (to, head [from]); head [from] = index ++;} tree; inline int get (_ int64 Val, int POS) {return (Val >>( POS <1 )) & 3;} inline void set (_ int64 & Val, int POs, int K) {Val | = (_ int64) k <(Pos <1) ;:__ int64 add (_ int64 A, _ int64 B) {_ int64 ans = 0; for (INT I = 0; I <K; I ++) {int AA = get (A, I); int BB = get (B, I); AA + = BB; Aa % = 3; Set (ANS, I, AA );} return ans ;}__ int64 fan (_ int64 A) {_ int64 ans = 0; For (INT I = 0; I <K; I ++) {int TMP = get (A, I); TMP = 3-TMP; Set (ANS, I, TMP % 3);} return ans;} bool vis [maxn]; __int64 Val [maxn] ;__ int64 ans; // The maximum number of subtree whose I node is the root int DP [maxn]; // int sum [maxn]; int sum; int min, m Inid; void dfs1 (int u, int f) {sum [u] = 1; DP [u] = 0; For (INT I = tree. Head [u]; ~ I; I = tree. edge [I]. NEX) {int CH = tree. edge [I]. to; If (CH = f | Vis [CH]) continue; dfs1 (CH, U); sum [u] + = sum [CH]; DP [u] = max (DP [u], sum [CH]) ;}} void dfs2 (int u, int f) {int M = max (DP [u], sum-sum [u]); If (M <min) {min = m; minid = u;} For (INT I = tree. head [u]; ~ I; I = tree. edge [I]. NEX) {int CH = tree. edge [I]. to; If (CH = f | Vis [CH]) continue; dfs2 (CH, u) ;}// return the center of gravity of the tree int getroot (int u) {// The First Time DFS finds the size of the subtree of all vertices, and the maximum number of subtree followed by child dfs1 (u, 0); sum = sum [u]; min = 0x3f3f3f; minid =-1; // calculate the center of gravity for the second DFS request/* If the whole tree calculates the center of gravity, we can only perform the DFS operation, because this is part of the tree, we need DFS to determine which nodes are in the current tree */dfs2 (u, 0); Return minid;} int tot ;__ int64 Val [maxn]; void getval (int u, int Fa, _ int64 vv) {Val [tot ++] = add (VV, Val [u]); For (INT I = tree. Head [u]; ~ I; I = tree. edge [I]. NEX) {int to = tree. edge [I]. to; If (vis [to] = true) continue; If (to = FA) continue; getval (to, U, add (VV, val [u]) ;}} map <__ int64, int> MP ;__ int64 CAL (INT root, _ int64 Val, _ int64 root_val) {tot = 0; getval (root, 0, Val); // sort (Val, Val + ToT); MP. clear (); _ int64 ans = 0; For (INT I = 0; I <tot; I ++) {ans + = MP [add (root_val, Fan (V Al [I])]; MP [Val [I] ++;} return ans;} void solve (INT U) {// obtain the center of gravity int root = getroot (u) of the current subtree; // calculate the root Root result ans + = CAL (root, 0, Val [root]); if (Val [root] = 0) ans ++; vis [root] = true; For (INT I = tree. head [root]; ~ I; I = tree. edge [I]. NEX) {int CH = tree. edge [I]. to; If (vis [CH]) continue; ANS-= CAL (CH, Val [root], Val [root]); solve (CH) ;}} int main () {While (scanf ("% d", & N )! = EOF) {scanf ("% d", & K); For (INT I = 0; I <K; I ++) {scanf ("% d ", & prime [I]);} tree. init (); memset (VIS, false, sizeof (VIS); memset (Val, 0, sizeof (VAL); For (INT I = 1; I <= N; I ++) {_ int64 TMP; scanf ("% i64d", & TMP); For (Int J = 0; j <K; j ++) {int CNT = 0; while (TMP % prime [J] = 0) {CNT ++; tmp/= prime [J];} CNT % = 3; set (Val [I], J, CNT) ;}}for (INT I = 0; I <n-1; I ++) {int U, V; scanf ("% d", & U, & V); tree. add (u, v); tree. add (v, U);} ans = 0; solve (1); printf ("% i64d \ n", ANS);} return 0 ;}
HDU 4670 cube number on a tree)