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 国际许可协议 进行许可。

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

  • 相关阅读:
    Nginx 部署多个 web 项目(虚拟主机)
    Nginx 配置文件
    Linux 安装 nginx
    Linux 安装 tomcat
    Linux 安装 Mysql 5.7.23
    Linux 安装 jdk8
    Linux 安装 lrzsz,使用 rz、sz 上传下载文件
    springMVC 拦截器
    spring 事务
    基于Aspectj 注解实现 spring AOP
  • 原文地址:https://www.cnblogs.com/Sam2007/p/12625607.html
Copyright © 2011-2022 走看看