Test instructions: To a tree with a weighted node of N, with a given k prime number as the factor, the number of path strips on the path of the product of the node is the cubic numbers
Idea: The cubic number of the properties of each factor is a multiple of 3, then each factor only need to save 0-2 three states can, and then the path can be converted to a K-bit 3-digit, after the point division, you can use a map to query the path through the root of the answer. The code is similar to the previous question (poj1741): http://www.cnblogs.com/jklongint/p/4960052.html
#pragma COMMENT (linker, "/stack:10240000,10240000") #include <iostream> #include <algorithm> #include < cstdio> #include <cstring> #include <ctime> #include <map> #include <vector>using namespace STD; #define X first#define Y second#define pb (x) push_back (x) #define MP (x, y) make_pair (x, y) #define ALL (a) (a). Begin (), ( a). End () #define MSET (A, X) memset (A, X, sizeof (a)) #define MCPY (A, B) memcpy (A, B, sizeof (b)) #define CAS () int T, cas = 0; Cin >> T; while (T--) template<typename T>bool UMAX (t&a, const t&b) {return a<b? A=b,true): false;} Template<typename T>bool umin (t&a, const t&b) {return b<a? ( A=b,true): false;} typedef long Long Ll;typedef pair<int, int> pii; #ifndef online_judge #include "local.h" #endifconst int N = 5e4 + 7;const int M = n;const int inf = 1e9 + 7;namespace Edge {int last[n], to[m << 1], next[m << 1], cnte; void Init () {cnte = 0; Memset (Last,-1, sizeof (last)); } void Addedge (int u, int v) {To[cnte] = V; Next[cnte] = Last[u]; Last[u] = Cnte + +; }}int N, k;struct Node {char p[33]; Char &operator[] (int x) {return p[x]; } ll Getnum () {ll ans = 0; for (int i = 0; i < K; i + +) {ans = ans * 3 + p[i]; } return ans; } ll Getcomplement () {ll ans = 0; for (int i = 0; i < K; i + +) {ans = ans * 3 + (P[i]? 3-p[i]: 0); } return ans; } node operator+ (node &that) {node ans; for (int i = 0; i < K; i + +) {Ans[i] = P[i] + that[i]; if (Ans[i] >= 3) ans[i]-= 3; } return ans; } node operator-(node &that) {node ans; for (int i = 0; i < K; i + +) {Ans[i] = P[i]-that[i]; if (Ans[i] < 0) Ans[i] + = 3; } return ans; }};namespace Center {int root, siz, son[n]; void Init () { Siz = inf; } void Getroot (int cur, int fa, int total, bool used[]) {son[cur] = 0; int buf = 0; for (int i = edge::last[cur]; ~i, i = Edge::next[i]) {int to = Edge::to[i]; if (to = FA &&!used[to]) {getroot (to, cur, total, used); Son[cur] + = son[to] + 1; BUF = Max (buf, son[to] + 1); }} BUF = Max (buf, Total-son[cur]-1); if (Buf < Siz | | buf = = siz && cur < siz) {siz = BUF; root = cur; }}}bool Used[n]; Node r[n];void getnode (int cur, int fa, Node sum, vector<node> &VT, bool used[]) {VT.PB (sum); for (int i = edge::last[cur]; ~i, i = Edge::next[i]) {int to = Edge::to[i]; if (to = FA &&!used[to]) getnode (to, cur, sum + r[to], VT, used); }}ll Getans (vector<node> &vt, Node &s) {ll ans = 0; Map<ll, Int> MP; for (int i = 0; I &Lt Vt.size (); i + +) {Mp[vt[i].getnum ()] + +; Ans + = mp[(Vt[i]-s). Getcomplement ()]; } return ans; ll work (int cur) {Used[cur] = true; Vector<node> Total; Total.push_back (R[cur]); ll ans = 0; for (int i = edge::last[cur]; ~i, i = Edge::next[i]) {int to = Edge::to[i]; if (!used[to]) {vector<node> local; GetNode (To, cur, r[cur] + r[to], local, used); Ans-= Getans (local, r[cur]); for (int j = 0; J < Local.size (); j + +) {Total.push_back (local[j]); } center::init (); Center::getroot (To, cur, local.size (), used); Ans + = Work (center::root); }} return ans + = Getans (total, r[cur]);} ll P[n], A[n];int main () {#ifndef Online_judge freopen ("In.txt", "R", stdin); Freopen ("OUT.txt", "w", stdout), #endif//Online_judge while (CIN >> n >> K) {edge::init (); Center::init (); MseT (r, 0); Mset (used, 0); for (int i = 0; i < K; i + +) {scanf ("%i64d", p + i); } for (int i = 1; I <= n; i + +) {scanf ("%i64d", A + i); for (int j = 0; J < K; J + +) {ll cur = p[j]; While (A[i]% cur = = 0) {R[i][j] + +; if (r[i][j] = = 3) R[i][j] = 0; Cur *= p[j]; }}} int u, v; for (int i = 1; i < n; i + +) {scanf ("%d%d", &u, &v); Edge::addedge (U, v); Edge::addedge (V, u); } center::getroot (1, 0, N, used); cout << Work (center::root) << Endl; } return 0;}
[hdu4670 Cube number on a tree] point division