• 520的信心赛——点点玩deeeep


                                                 3、点点玩 deeeep(deeeep.cpp)

    描述
      点点最近迷上了 deeeep(此 de 非彼 de),在研究一个特殊的
    最长树链问题(树链即树上的一条路径)。现在一棵树中的每个点
    都有一个 deeeep 值(正整数)
    ,点点想在树中找出最长的树链,使
    得这条树链上所有对应点的 deeeep 值的最大公约数大于 1。请求出
    这条树链的长度。(巨说这道题很 water!
    )
    格式
    输入格式
    第 1 行:整数 n(1 ≤ n ≤ 100000),表示点的个数。
    第 2~n 行:每行两个整数 x,y 表示 x 和 y 之间有边,数据保证给
    出的是一棵树。
    第 n+1 行:n 个整数,依次表示点 1~n 对应的权值(1 ≤ 权值 ≤
    1,000,000,000)

    输出格式输出一个整数,表示这条树链的长度。
    样例 1
    样例输入 1
    4
    1 2
    1 3
    2 4
    6 4 5 2
    样例输出 1
    3
    限制
    对于 100%的数据 1≤n≤100000,1≤ai≤10^9

    Solution:

      本题考察搜索+数学。
        实际上就是乱写暴力。bfs爆搜能ac,还比正解快,简直鬼畜。
        枚举每个约数,保留对应的边,做一次最长路径。因为一个数的约数个数可以保证,所以复杂度符合要求。
        看起来10^9很虚,但是我们分解质因数只需要预处理出3*10^4里的质数,实际上只有3000多个,3000*n完全不虚,所以我们可以先将n个数全都分解质因数。
      然后我们枚举每个质数,枚举所有包含这些质数的点,看一下这些点在树上能形成的最长的链有多长。具体做法是我们将这些点按照深度从大到小排序,然后更新每个点父亲的子树中到父亲的最长链、次长链分别是多长,乱搞一下就行了。

    代码:

    bfs玄学比正解快:

     1 /*莫名打的玄学复杂度bfs,结果ac——by 520*/
     2 #include<bits/stdc++.h>
     3 #define il inline
     4 using namespace std;
     5 const int maxn = 100050;
     6 int maxlen=0,rd[maxn],a[maxn];
     7 vector<int>v[maxn];
     8 il int gi()
     9 {
    10     int a=0;char x=getchar();bool f=0;
    11     while((x<'0'||x>'9')&&x!='-')x=getchar();
    12     if(x=='-')x=getchar(),f=1;
    13     while(x>='0'&&x<='9')a=a*10+x-48,x=getchar();
    14     return f?-a:a;
    15 }
    16 struct node{
    17     int x;
    18     int len;
    19     int gcd;
    20 };
    21 il void bfs(int x,int len,int gcd)
    22 {
    23     node n1,n2;
    24     queue<node>q;
    25     n1.x=x; n1.len=len; n1.gcd=gcd;
    26     q.push(n1);
    27     while(!q.empty())
    28     {
    29         node n1=q.front(); q.pop();
    30         int nx=n1.x, nlen=n1.len, ngcd=n1.gcd;
    31         maxlen=max(nlen, maxlen);
    32         for(int i=0;i<v[nx].size();i++)
    33         {
    34             int next=v[nx][i], usegcd=__gcd(a[next],ngcd);
    35             if(usegcd==1){
    36                 n2.gcd=a[next]; n2.len=1; n2.x=next;
    37                 q.push(n2);
    38             }
    39             else{
    40                 n2.gcd=usegcd; n2.len=1+nlen; n2.x=next;
    41                 q.push(n2);
    42             }
    43         }
    44     }
    45 }
    46 int main()
    47 {
    48     freopen("deeeep.in","r",stdin);
    49     freopen("deeeep.out","w",stdout);
    50     int x,y,n=gi(),go=0;
    51     for(int i=2;i<=n;i++)
    52     {
    53         x=gi(),y=gi();
    54         v[x].push_back(y);
    55         rd[y]++;
    56     }
    57     for(int i=1;i<=n;i++)
    58     {
    59         if(rd[i]==0)go=i;
    60         a[i]=gi();
    61     }
    62     bfs(go,1,a[go]);
    63     printf("%d",maxlen);
    64     return 0;
    65 }

    正解:

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <cmath>
     6 #include <vector>
     7 #include <map>
     8 using namespace std;
     9 int n,m,cnt,ans,tot,mor;
    10 const int maxn=100010;
    11 int to[maxn<<1],nxt[maxn<<1],head[maxn],v[maxn],d1[maxn],d2[maxn],p[103600],fa[maxn],dep[maxn],pri[3600];
    12 bool np[33000];
    13 vector<int> s[103600];
    14 map<int,int> mp;
    15 int rd()
    16 {
    17     int ret=0;  char gc=getchar();
    18     while(gc<'0'||gc>'9') gc=getchar();
    19     while(gc>='0'&&gc<='9')   ret=ret*10+gc-'0',gc=getchar();
    20     return ret;
    21 }
    22 void dfs(int x)      
    23 {
    24     for(int i=head[x];i!=-1;i=nxt[i])   if(to[i]!=fa[x])    fa[to[i]]=x,dep[to[i]]=dep[x]+1,dfs(to[i]);
    25 }
    26 bool cmp1(int a,int b)
    27 {
    28     return s[a].size()>s[b].size();
    29 }
    30 bool cmp2(int a,int b)  
    31 {
    32     return dep[a]>dep[b];
    33 }
    34 void updata(int a,int b) 
    35 {
    36     if(d1[b]>d1[a])  d2[a]=d1[a],d1[a]=d1[b];
    37     else    d2[a]=max(d2[a],d1[b]);
    38 }
    39 void add(int a,int b)  
    40 {
    41     to[cnt]=b,nxt[cnt]=head[a],head[a]=cnt++;
    42 }
    43 int main()
    44 {
    45     freopen("deeeep.in","r",stdin);
    46     freopen("deeeep.out","w",stdout);
    47     n=rd();
    48     int i,j,a,b;
    49     memset(head,-1,sizeof(head));
    50     for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
    51     for(i=1;i<=n;i++)    v[i]=rd(),m=max(m,v[i]);      
    52     m=ceil(sqrt(1.0*m));         
    53     for(i=2;i<=m;i++)            
    54     {
    55         if(!np[i])  pri[++tot]=i,mp[i]=tot; 
    56         for(j=1;j<=tot&&i*pri[j]<=m;j++)
    57         {
    58             np[i*pri[j]]=1;
    59             if(i%pri[j]==0) break;
    60         }
    61     }
    62     dep[1]=1,dfs(1),mor=tot;  
    63     for(i=1;i<=n;i++)
    64     {
    65         for(j=1;j<=tot&&pri[j]*pri[j]<=v[i];j++)
    66         {
    67             if(v[i]%pri[j]==0)
    68             {
    69                 s[j].push_back(i);  
    70                 while(v[i]%pri[j]==0)   v[i]/=pri[j];
    71             }
    72         }
    73         if(v[i]>1)
    74         {
    75             if(mp.find(v[i])==mp.end()) mp[v[i]]=++mor;
    76             s[mp[v[i]]].push_back(i);
    77         }
    78     }
    79     ans=1;
    80     for(i=1;i<=mor;i++)  p[i]=i;
    81     sort(p+1,p+mor+1,cmp1);
    82     for(i=1;i<=mor;i++)
    83     {
    84         b=p[i];
    85         if(s[b].size()<=ans) break;
    86         sort(s[b].begin(),s[b].end(),cmp2);
    87         for(j=0;j<s[b].size();j++)   a=s[b][j],d1[a]++,d2[a]++,ans=max(ans,d1[a]+d2[a]-1),updata(fa[a],a);
    88         for(j=0;j<s[b].size();j++)   a=s[b][j],d1[a]=d2[a]=d1[fa[a]]=d2[fa[a]]=0;
    89     }
    90     printf("%d",ans);
    91     return 0;
    92 }
  • 相关阅读:
    ES6笔记
    JavaScriptOOP (三)
    JavaScriptOOP(二)
    JavaScriptOOP(一)
    基于vue-cli 将webpack3 升级到 webpack4 配置
    JavaScript 中 call,apply 和 bind
    vue 2.6 更新变动
    JavaScript严格模式
    vue 修饰符 整理
    webpack打包将配置文件单独抽离不压缩打包
  • 原文地址:https://www.cnblogs.com/five20/p/8410510.html
Copyright © 2020-2023  润新知