• 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
  • 相关阅读:
    linux使用jstack来找出死循环的java代码
    Dubbo的几种序列化协议
    上传新项目到GitLab
    PI Network项目,手把手教快速挖Pi币
    Oracle数据导出、导入
    如何实现表单标题两端对齐
    cookie 操作记录& vuex 中页面刷新 state 数据丢失的问题
    FCSAN存储与服务器关联映射后在服务器端如何识别操作
    修改密码报-bash: !@#***": event not found
    springboot整合logstash
  • 原文地址:https://www.cnblogs.com/yang-RA-NOI/p/12594636.html
Copyright © 2020-2023  润新知