zoukankan      html  css  js  c++  java
  • 【CF 1101D|GOJ 3501】GCD Counting

    题目传送门:

    1. https://codeforces.com/problemset/problem/1101/D
    2. http://u.gdfzoj.com/problem/3501

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


    首先,我们先明白一件事情:题目要求我们的(gcd)之和不等于(1),指的是我们并不关心(gcd)的值是多少,只要它大于(1)即可。(gcd)不是(1),意味着一定有公共质因子。

    接下来就好办了,我们可以用(f[x][j])表示以(x)为根的子树往下走,公共质因子为(j)的最大值

    又因为不同的质因子个数十分少,所以几乎可以看成一个常数,可以暴力处理每一个节点的信息。显然最优解一定会被处理到。


    代码:

    #include<bits/stdc++.h>
    namespace Bu_Yao_Tian_Tian_Bi_Sai {
    	using namespace std;
    #define LL long long
    	inline LL read() {
    		char c=getchar();
    		LL sum=0;
    		while(c<'0'||c>'9') {
    			c=getchar();
    		}
    		while(c>='0'&&c<='9') {
    			sum=(sum<<3)-'0'+(sum<<1)+c,c=getchar();
    		}
    		return sum;
    	}
    	inline void write(LL x) {
    		if(x>9) {
    			write(x/10);
    		}
    		putchar(x%10+'0');
    	}
    	const int d[4][2]= {
    		{1,0},{0,1},{-1,0},{0,-1}
    	},mod=1e9+7,N=1e6+5;
    }
    using namespace Bu_Yao_Tian_Tian_Bi_Sai;
    struct edge {
    	int to,nxt;
    } e[N<<1];
    int head[N],cnt,ans=1;
    inline void add(int u,int v) {
    	e[++cnt].to=v,e[cnt].nxt=head[u],head[u]=cnt;
    }
    vector<int> p[N],f[N];
    //p[u]:对u分解质因数后的结果
    //f[u][v]:u为根的子树,往下走,公共质因子为v的最长链
    int max(int u,int v) {
    	return u<v?v:u;
    }
    void dfs(int u,int fa) {
    	for(int i=head[u]; i; i=e[i].nxt) {
    		int v=e[i].to;
    		if(v==fa) {
    			continue ;
    		}
    		dfs(v,u);
    		for(int j=0; j<p[u].size(); j++) {
    			for(int k=0; k<p[v].size(); k++) {
    				if(p[u][j]==p[v][k]) {
    					ans=max(ans,f[u][j]+f[v][k]);//连接两条路径
    					f[u][j]=max(f[u][j],f[v][k]+1);
    				}
    			}
    		}
    	}
    }
    void fen(int x,int tmp) {
    	for(int i=2; i*i<=x; i++) {
    		if(x%i==0) {
    			p[tmp].push_back(i),f[tmp].push_back(1);
    			while(x%i==0) {
    				x/=i;
    			}
    		}
    	}
    	if(x>1) {
    		p[tmp].push_back(x),f[tmp].push_back(1);
    	}
    }
    int main() {
    	int n=read();
    	bool flag=0;
    	for(int i=1,x; i<=n; i++) {
    		x=read();
    		if(x^1) {
    			flag=1;
    		}
    		fen(x,i);
    	}
    	if(!flag) {
    		write(0);
    		return 0;
    	}
    	for(int i=1,u,v; i<n; i++) {
    		u=read(),v=read(),add(u,v),add(v,u);
    	}
    	dfs(1,0);
    	write(ans);
    	return 0;
    }
    /*
      _  __
     (_)/   
    <'_, ____)~~~~~~~
      ^^   ^^
    */
    

    完美撒花~

    知识共享许可协议

    本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

    限于本人水平,如果文章有表述不当之处,还请不吝赐教。

  • 相关阅读:
    索引优化策略
    mysql列类型选择
    redis安装
    redis相关面试题
    aop动态代理源码分析
    JVM运行时数据区
    redis应用场景
    JPA相关知识
    技术栈
    linux上安装mysql5.6
  • 原文地址:https://www.cnblogs.com/Sam2007/p/12625607.html
Copyright © 2011-2022 走看看