题目描述
Recently, Miss Huang want to receive a Tree as her birthday gift! (What a interesting person!) As a interesting person, Miss Huang likes interesting tree.
The interesting tree is a tree with the Max interesting degree. The interesting degree equals LCM(H(1),H(2), .. , H(N)), H(x) means the height of node x in the tree and LCM means least common multiple.
Now Mr Chen has some non-rooted tree, he wants you to choose a root of the non-rooted tree and make the strange degree of tree be maximum;
The answer may be very large please print the answer mod 10^9+7.
输入
Your program will be tested on one or more test cases. In each test case:
First line a number N(1<=N<=10^5) represent the number of node.
The next N-1 line has two number u, v indicates that there is a edge between u, v.
输出
For every test case, print the following line:
answer
where answer is the maximum LCM.(mod 10^9+7)
样例输入
41 21 31 421 2
样例输出
62
题解:问题分两步:
1.求树的直径:即树种距离最长的两个点之间的距离
2.求从1到n这n个数的最小公倍数.
先说第一个问题,有两种方法:深搜和广搜.
先说深搜:对于树的某个节点,它的最深的两个儿子m1,m2.
那么很显然m1+m2+1有可能是树的直径.用这个数更新树的直径
再说广搜:1.随机选取一个节点A进行广搜,从而找到距离它最远的结点B.当然B可能不唯一.
2.B必然是此树某个直径的一个端点(树的直径可能不唯一).
从B开始广搜找到离B最远的C结点.BC极为直径.
再说第二个问题:有两种方法,其中一种是错的.
先说正确的:比如从1到9.既然有8,那么4,2就没法说话了,山上有老虎,猴子怎能称大王.
既然有9,那么3就没法说话了.
规律出来了:全体质数打表求出来,2,3,5,7.
再说错误的: 对于任意一个序列a[],求其全部元素的最小公倍数.怎么求?
求其全部元素的最大公约数怎么求?这个你会.两两求,从头扫描到尾.
但是这道题里不行,必须进行质因数分解,因为有取模运算!!!!!!!!!! 取模之后就没法再求最大公倍数了!!!!!!!!!!!!!!!!
比赛的时候,我就错在了这里,我真傻真的
#include<iostream> #include<list> #include<math.h> #include<stdio.h> #include<string.h> using namespace std; const int maxn = 1e5 + 7; const int big = 1e9 + 7; int N; struct Edge{ int to, next; }e[maxn*2]; int g[maxn],ei; bool vis[maxn]; int maxLen; int prime[maxn / 5], psize; void init(){ bool is[maxn]; psize = 0; memset(is, 1, sizeof(is)); for (int i = 2; i < maxn; i++){ if (is[i]){ prime[psize++] = i; } for (int j = 0; i*prime[j] < maxn; j++){ is[i*prime[j]] = 0; if (i%prime[j] == 0)break; } } } void push_back(int from, int to){ e[ei].next = g[from]; e[ei].to = to; g[from] = ei++; } int deep(int x){ int m1, m2; vis[x] = 1, m1 = m2 = 0; for (int i = g[x]; i; i = e[i].next){ int t = e[i].to; if (vis[t] == false){ int d = deep(t); if (m2<d){ if (m1<d){ m2 = m1, m1 = d; } else m2 = d; } } } int len = m1 + m2 + 1; if (len > maxLen)maxLen = len; return m1 + 1; } int main(){ //freopen("in.txt", "r", stdin); init(); while (~scanf("%d", &N)){ ei = 1, memset(g, 0, sizeof(int)*(N + 1)); int x, y; for (int i = 1; i < N; i++)scanf("%d%d", &x, &y), push_back(x, y), push_back(y, x); memset(vis, 0, sizeof(bool)*(N + 1)); maxLen = 0; deep(1); long long int ans = 1; for (int i = 0; i < psize; i++){ int mi = floor(log(maxLen) / log(prime[i])); if (mi == 0)break; ans *= pow(prime[i], mi); ans %= big; } cout << ans << endl; } return 0; } /************************************************************** Problem: 1578 User: 20124003 Language: C++ Result: 正确 Time:181 ms Memory:9568 kb ****************************************************************/