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

    题目链接

    题意分析

    求解最长路径的问题 我们可以使用DP

    但是这里求GCD比较恶心 我们可以转换思路

    gcd(x,y)≠1 说明x,y之间必然存在公共质因子 那么我们可以通过枚举质因子代替gcd

    由于2×3×5×7×11×13×17×19=9699690>200000 所以枚举质因子对于复杂度几乎无影响

    然后使用树形DP就可以了

    CODE:

    #include<bits/stdc++.h>
    #define M 408611
    #define INF 200080
    using namespace std;
    int n,tot,cnt,root,sum,ans;
    int num[M];
    int to[M],nex[M],head[M];
    int dp[M][10];
    int prime[M];
    bool mark[M];
    vector<int> G[M];
    void add(int x,int y)
    {to[++tot]=y;nex[tot]=head[x];head[x]=tot;}
    void pre()
    {
    	for(int i=2;i<=INF;++i)
    	{
    		if(!mark[i]) prime[++tot]=i;
    		for(int j=1;j<=tot&&prime[j]*i<=INF;++j)
    		{
    			mark[prime[j]*i]=1;
    			if(i%prime[j]==0) break;
    		}
    	}
    	for(int i=1;i<=tot;++i)\\预处理质因子
    	 for(int j=prime[i];j<=INF;j+=prime[i])
    	  G[j].push_back(prime[i]);
    }
    void dfs(int now,int fat)
    {
    	for(int i=0;i<(int)G[num[now]].size();++i) dp[now][i]=1;
    	for(int x=head[now];x;x=nex[x])
    	{
    		int v=to[x];
    		if(v==fat) continue;
    		dfs(v,now); 
    		for(int i=0;i<(int)G[num[now]].size();++i)
    		 for(int j=0;j<(int)G[num[v]].size();++j)
    		  {//枚举质因子 如果存在相同的话就转移
    		  	if(G[num[now]][i]!=G[num[v]][j]) continue;
    			ans=max(ans,dp[now][i]+dp[v][j]);
    			dp[now][i]=max(dp[now][i],dp[v][j]+1);   
    		  }
    	}
    }
    int main()
    {
    	pre();tot=0;
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i)
    	{
    		scanf("%d",&num[i]);
    		if(num[i]>1) ans=1;
    	} 
    	for(int i=1,x,y;i<n;++i)
    	{
    		scanf("%d%d",&x,&y);
    		add(x,y);add(y,x);
    	}
    	dfs(1,0);
    	printf("%d\n",ans);
    	return 0;
    } 
    
  • 相关阅读:
    python操作elasticsearch
    php源码的编译
    linux 访问windows 共享文件
    list容器排除重复单词的程序
    求组合数m_n
    简单堆排序
    快速排序
    判断点在直线左侧或者右侧
    求取点到直线的距离
    求给定三个点的夹角
  • 原文地址:https://www.cnblogs.com/tcswuzb/p/14457223.html
Copyright © 2011-2022 走看看