zoukankan      html  css  js  c++  java
  • CF1101D GCD Counting

    题目传送门:CF1101D

    洛谷入口

    题目大意:

    (给出一棵n个节点的树,每个节点上有点权a_i)
    (求最长的树上路径,满足条件:)
    (路径上经过节点(包括两个端点)点权的gcd和不等于1)

    数据范围

    (circ) (nle2 imes10^5)
    (circ) (1le a_ile2 imes10^5)

    题解

    首先当然会想到
    若要几个的gcd不等于0
    我们可以用他们的其中一个非1的因数DP
    向下DP显然不妙,于是决定DFS树,回溯时去DP
    那么对于一个点,遍历他的儿子
    对于每一个子节点回溯时找他们两个的所有相同质因子
    进行DP,同时更新答案
    最后输出答案即可
    对于找共同质因子,只要预先处理:
    先找到质数家族,
    再一个一个(a_i)分解质因数,把它们放在数组里储存。
    怕数组空间炸?不用担心,一个数最多也就(7,8)个不同的质因子
    ((2 imes3 imes5 imes7 imes9 imes11 imes13 imes17>2 imes10^5))
    所以就问题不大了!详见下方代码↓↓↓

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    int tot=0,n,cnt,head[200010];
    int maxx=200010,a[200010],vis[300010],f[200010][10],y[200010][10],ans,p[200010];
    //p是质数家族 ,y[i][j]是指a[i]的第j大的质因子 
    struct abc{
    	int to,nxt;
    }e[800010];
    void add(int u,int v){
    	e[++cnt].nxt=head[u];
    	e[cnt].to=v;
    	head[u]=cnt;
    }
    void make_zhi(){//求质数的欧拉筛,不懂自行百度(相信各位大佬定会的) 
    	for(int i=2;i<=maxx;i++){
    		if(!vis[i])p[++tot]=i;
    		for(int j=1;j<=tot&&p[j]*i<=maxx;j++){
    			vis[i*p[j]]=1;
    			if(i%p[j]==0)break;
    		}
    	}
    	//cout<<p[10]<<endl;
    }
    void dfs(int u,int fa){
    	for(int i=head[u];i;i=e[i].nxt){
    		int v=e[i].to;
    		if(fa==v)continue;
    		dfs(v,u);
    		for(int j=1;j<=y[u][0];j++){
    			for(int k=1;k<=y[v][0];k++){
    				if(y[u][j]==y[v][k]){
    					ans=max(ans,f[u][j]+f[v][k]+1);
    					f[u][j]=max(f[u][j],f[v][k]+1);
    				}
    			}
    		}
    	}
    }
    int main(){
    	make_zhi();
    	int ff=1;
    	cin>>n;
    	for(int i=1;i<=n;i++){
    		cin>>a[i];
    		if(a[i]!=1)ff=0;
    	}
    	for(int i=1;i<n;i++){
    		int u,v;
    		cin>>u>>v;
    		add(u,v);add(v,u);
    	}
    	if(ff){//特判全1时 
    		cout<<0;
    		return 0;
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=1;p[j]*p[j]<=a[i];j++){
    			if(a[i]==1)break;
    			if(a[i]%p[j]==0){
    				y[i][++y[i][0]]=p[j];//太懒于是用y[i][0]存质数个数 
    				while(a[i]%p[j]==0)a[i]/=p[j];//统统除掉 
    			}
    		}
    		if(a[i]!=1)y[i][++y[i][0]]=a[i];//剩下了他自己怎么办?靠他了 
    	}
    	dfs(1,0);
    	cout<<ans+1;
    } 
    //加一什么的多调几次就会发现的了 
    

    支持一下吧,关注,点赞,评论都好!

    THE END

    Reality&Imagine
  • 相关阅读:
    CSS盒子模型
    getContextPath、getServletPath、getRequestURI、request.getRealPath的区别
    MYSQL中的CASE WHEN END AS
    单点登录的精华总结
    git&github
    June 21st 2017 Week 25th Wednesday
    June 20th 2017 Week 25th Tuesday
    June 19th 2017 Week 25th Monday
    June 18th 2017 Week 25th Sunday
    June 17th 2017 Week 24th Saturday
  • 原文地址:https://www.cnblogs.com/yang-RA-NOI/p/12594636.html
Copyright © 2011-2022 走看看