• 2015年辽宁省赛Interesting Tree


    题目描述

    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
    ****************************************************************/


  • 相关阅读:
    在数组中的两个数字如果前面一个数字大于后面的数字, 则这两个数字组成一个逆序对。 输入一个数组,求出这个数组中的逆序对的总数
    输入一个正整数数组,把数组里所有数字拼接起来排成一个数。打印能拼接出所有数字中最小的一个
    输入一个整型数组,数组里有正数,也有负数。求所有子数组的和的最大值
    数组中有一个数字出现的次数超过数组长度的一半
    输入一个字符串,打印出该字符串中字符的所有排列
    输入一颗二叉搜索树,将该二叉搜索树转换成一个排序的双向链表
    输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径
    判断某数组是否是某二叉搜索树的后序遍历的结果
    栈的压人、弹出序列
    Valid Number
  • 原文地址:https://www.cnblogs.com/weiyinfu/p/5013884.html
Copyright © 2020-2023  润新知