题意:给你一颗树,树上的每个顶点有一个权值,给定一个数k,让你找一条路径,使得这条路径上的点的权值的乘积模上一个数后等于k.
解题思路:这是一道树分治的经典题目,也是我做的第一道树分治的题目,这题的话比较简单,几乎模板,需要注意的地方是逆元要一次求出,还要注意一下hash的地方,写的太丑会t.
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 1e6 + 10; const LL mod = 1e6 + 3; int N, K; int E; bool flag; int Size, Maxn; LL inv[maxn];//逆元 int head[maxn]; LL value[maxn]; int Hash[maxn]; bool visit[maxn]; pair<int, int> ans; int dp[maxn];//以i为根的子树的节点数 int root; vector<pair<int, LL> > temp; struct edge{ int v, Nxt; }Edge[maxn<<1]; void add_edge(int u, int v) { Edge[E].v = v; Edge[E].Nxt = head[u]; head[u] = E++; } void init() { memset(head, -1, sizeof(head)); memset(visit, false, sizeof(visit)); memset(Hash, -1, sizeof(Hash)); flag = false; temp.clear(); root = -1; E = 0; } LL quick_mod(LL x, LL i) { LL ans = 1; ans %= mod; while(i) { if(i&1) ans = (ans * x) % mod; i >>= 1; x = (x * x) % mod; } return ans; } void getInv() { for(int i = 1; i <= (int)mod; i++) { inv[i] = quick_mod((LL)i, mod - 2); } } void getRoot(int u, int fa)//找出树的重心 { dp[u] = 1; int Max = 0; for(int i = head[u]; i != -1; i = Edge[i].Nxt) { int v = Edge[i].v; if(v == fa) continue; if(!visit[v]) { getRoot(v, u); dp[u] += dp[v]; Max = max(Max, dp[v]); } } Max = max(Max, Size - dp[u]); if(Max < Maxn) { Maxn = Max; root = u; } } void getDis(int u, int fa, LL x) { LL res = x * value[u] % mod; temp.push_back(make_pair(u, res)); for(int i = head[u]; i != -1; i = Edge[i].Nxt) { int v = Edge[i].v; if(v == fa) continue; if(!visit[v]) { getDis(v, u, res); } } } void update(int u, int v) { if(u > v) swap(u, v); if(!flag) { flag = true; ans = make_pair(u, v); } else { if(u < ans.first) ans = make_pair(u, v); else if(u == ans.first && v < ans.second) ans = make_pair(u, v); } } LL d[maxn]; void work(int u) { visit[u] = true; int cnt = 0; for(int i = head[u]; i != -1; i = Edge[i].Nxt) { int v = Edge[i].v; if(visit[v]) continue; temp.clear(); getDis(v, v, value[u]); for(int j = 0; j < temp.size(); j++) { int id = temp[j].first; LL x = temp[j].second; if(x == K) update(id, u); LL judge = (inv[x] % mod * K) % mod; if(Hash[judge] == -1) continue; else { update(id, Hash[judge]); } } for(int j = 0; j < temp.size(); j++) { int id = temp[j].first; LL x = temp[j].second; x = (x * inv[value[u]]) % mod; d[++cnt] = x; if(Hash[x] == -1) Hash[x] = id; else { Hash[x] = min(Hash[x], id); } } } for(int i = 1; i <= cnt; i++) Hash[d[i]] = -1; for(int i = head[u]; i != -1; i = Edge[i].Nxt) { int v = Edge[i].v; if(visit[v]) continue; Maxn = dp[v]; Size = dp[v]; root = -1; getRoot(v, v); work(root); } } int main() { getInv(); while(~scanf("%d%d", &N, &K)) { init(); for(int i = 1; i <= N; i++) { scanf("%lld", &value[i]); } int u, v; for(int i = 1; i < N; i++) { scanf("%d%d", &u, &v); add_edge(u, v); add_edge(v, u); } Maxn = N; Size = N; getRoot(1, 1); work(root); if(flag) printf("%d %d\n", ans.first, ans.second); else printf("No solution\n"); } return 0; }