zoukankan      html  css  js  c++  java
  • hihoCoder挑战赛4 光棍节

    题目3 : 光棍节

    时间限制:30000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    尽管付出了种种努力,jzp还是得过光棍节。

    jzp非常不爽,但也无能为力,只能够哀叹起来他的命运。他想到了一位长者的人生经验:“人的一生,不光要靠自我奋斗,也要考虑历史的进程”。

    他终于明白自己只是时运不济,所以又继续开始努力。终于在圣诞节当天把到了妹子。

    jzp从此过上了快乐的现充生活,在圣诞节当天,他还和妹子玩起了有趣的游戏:

    jzp的家里有一棵非常大的圣诞树,可以看成是一个n个点的无向联通无环图。每个点上都有一个正整数,JZP和妹子每次都会选择树上的一条路径,

    这条路径的权值被定义为路径上所有点上数的最大公约数,JZP可以得到这个权值的分数。

    JZP玩了一会儿有点腻了,他想知道对于每种可能的权值x,权值为x的不同路径的数量(a到b的路径和b到a的路径算作一种,a到a自身也算作一条路径。)

    输入

    第一行一个整数n(1<=n<=105)表示圣诞树的大小,点从1开始标号。

    接下来一行n个整数用单个空格隔开,第i个表示第i个点上的数。(数都在1到105之间)。

    接下来n-1行,每行两个数a和b,表示a和b之间有一条边。

    输出

    令C(x)表示权值为x的路径的个数。

    从小到大输出对于所有C(x)>0的x,输出一行两个数x和C(x),用空格隔开。

    样例输入
    20
    2 4 2 4 2 4 2 20 20 12 12 12 2 12 2 4 4 2 12 2
    1 2
    1 3
    1 4
    2 5
    3 6
    1 7
    6 8
    2 9
    6 10
    5 11
    4 12
    11 13
    10 14
    3 15
    9 16
    7 17
    4 18
    4 19
    16 20
    样例输出
    2 186
    4 16
    12 6
    20 2

    思路:一看就是树分治的题,可是想想都会T 啊,可是实在没事可以做,所以只有去暴力了,加了一些优化,
    交了wa,改了改,还是wa 。。。。 后面把优化全部去掉,终于T了,好像很兴奋的样子
    后面看了代码,发现一个地方错了,可是只有几分钟了。。。。
    改了交,然后有把优化加上,又交了一发。
    然后结束了,心里想又挂0 了。。。
    后面没加优化的过了。。。。。==
    最后一分钟过的。。不容易呀
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<set>
    #include<stack>
    #include<map>
    #include<ctime>
    #include<bitset>
    #define LL long long
    #define ll long long
    #define INF 0x3f3f3f3f
    #define maxn 200010
    #define eps 1e-6
    #define mod 1000000007
    using namespace std;
    
    int head[maxn] , to[maxn*2] ,next1[maxn*2] ;
    int top ,cnt[maxn] , f[maxn];
    int  k ,ans ,n ;
    vector<int>vec;
    bool vi[maxn] ;
    
    void Unit(int x,int y)
    {
        to[top]=y;next1[top]=head[x] ;
        head[x]=top++;
    }
    void find1( int u ,int fa )
    {
        f[u] = 0 ;
        cnt[u] = 1 ;
        int v ;
        for( int i = head[u] ; i != -1; i = next1[i])
        {
             v = to[i] ;
            if(v==fa||vi[v]) continue ;
            find1(v,u) ;
            cnt[u] += cnt[v] ;
            f[u] = max(cnt[v],f[u]) ;
        }
    }
    int minn ;
    void find_root1( int u ,int fa,int &root,int sum)
    {
        int tmp = max(sum-cnt[u],f[u]) ;
        if(tmp < minn)
        {
            minn = tmp ;
            root = u ;
        }
        int v;
        for( int i = head[u] ; i != -1; i = next1[i])
        {
            v = to[i] ;
            if(v==fa||vi[v]) continue ;
            find_root1(v,u,root,sum) ;
        }
    }
    
    int get_root( int u )
    {
        find1(u,-1) ;
        int sum = cnt[u] ;
        int root = u ;
        minn = n ;
        find_root1(u,-1,root,sum) ;
        return root ;
    }
    int ret ,MAX,num[maxn],val[maxn] ;
    LL c[maxn];
    int gcd(int a,int b)
    {
        int c;
        while(b)
        {
            c = a%b ;
            a = b ;
            b = c ;
        }
        return a ;
    }
    int num1,num2;
    vector<int>q;
    void find(int d)
    {
        int x,n=q.size();
        for(int i =0 ; i < n ;i++)
        {
            x = gcd(q[i],d) ;
            c[x] += num[q[i]] ;
        }
    }
    void dfs1(int u ,int fa,int root,int d )
    {
        vec.push_back(d);
        c[d]++;
       /* if(d==1)c[1] += num1 ;
        else if(d==2) c[2] += num2 ;*/
        find(d) ;
        int j,v ;
        for( int i = head[u] ; i != -1 ; i = next1[i])
        {
             v = to[i] ;
            if(vi[v]||v==fa) continue ;
            dfs1(v,u,1,gcd(d,val[v])) ;
        }
    }
    int que[maxn],l;
    void count( int u )
    {
        int j,v ;
        l=0;
        num1=num2=0;
        q.clear();
        for( int i = head[u] ; i != -1 ; i = next1[i])
        {
            v = to[i] ;
            if(vi[v]) continue ;
            vec.clear() ;
            dfs1(v,u,-1,gcd(val[u],val[v]));
            for( j = 0 ; j < vec.size();j++){
                if(num[vec[j]]==0)q.push_back(vec[j]);
                num[vec[j]]++ ;
                num1++;
                if(vec[j]&1){}
                else num2++;
                que[l++]=vec[j];
            }
        }
        for( int i = 0 ; i < l ;i++)
            num[que[i]] = 0;
    }
    void solve( int u )
    {
        int root = get_root(u) ;
        vi[root] = 1 ;
        count(root) ;
        int v ;
        for( int i = head[root] ; i != -1 ; i = next1[i])
        {
            v = to[i] ;
            if(vi[v]) continue ;
            solve(v) ;
        }
    }
    
    int main()
    {
        int i ,  m ,k , j ;
        int x,y;
        while(scanf("%d",&n) != EOF)
        {
            MAX=0;
            memset(c,0,sizeof(c)) ;
            memset(num,0,sizeof(num));
            for( i = 1 ; i <= n ;i++){
                scanf("%d",&val[i]) ;
                c[val[i]]++;
                MAX=max(MAX,val[i]) ;
            }
            memset(head,-1,sizeof(head)) ;
            memset(vi,0,sizeof(vi));
            top=0;
            for(i = 1 ; i < n ;i++)
            {
                scanf("%d%d",&x,&y) ;
                Unit(x,y) ;
                Unit(y,x) ;
            }
            solve(1) ;
            for( i =1 ; i <= MAX;i++)if(c[i]>0)
            {
               cout<<i<<" "<<c[i]<<endl;
            }
        }
        return 0 ;
    }
    View Code
  • 相关阅读:
    【LeetCode-树】二叉搜索树中第K小的元素
    【机器学习-评估方法】模型评估方法
    【LeetCode-树】二叉搜索树的最小绝对差
    【LeetCode-树】检查平衡性
    【LeetCode-树】验证二叉搜索树
    【LeetCode-回溯/动态规划】不同路径
    Vue——风格指南
    潜在危险
    渲染HTML的方式
    Vue——状态管理
  • 原文地址:https://www.cnblogs.com/20120125llcai/p/4070217.html
Copyright © 2011-2022 走看看