CF1101D GCD Counting

CF1101D GCD Counting

又被trick了

不用什么点分治

直接树形dp即可

开始的想法:

f[x][j]x为根的子树gcd至少为j(j是x的一个约数)的最长链

然后对y合并。类似于树的直径

但是复杂度还是很大的。。。

这个题的关键是:我们只关心gcd是不是1,并不关心gcd是什么!

gcd不是1,意味着一定有公共质因子!

而质因子个数非常少

可以f[x][j]表示,x为根的子树,往下走,公共质因子为j的最长链

然后甚至可以暴力合并!

显然最优解可以被处理到!

代码:

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^‘0‘)
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch==‘-‘)&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
const int N=2e5+5;
vector<int>p[N],f[N];
int n;
int ans;
struct node{
    int nxt,to;
}e[2*N];
int hd[N],cnt;
void add(int x,int y){
    e[++cnt].nxt=hd[x];
    e[cnt].to=y;
    hd[x]=cnt;
}
void dfs(int x,int fa){
    for(reg i=hd[x];i;i=e[i].nxt){
        int y=e[i].to;
        if(y==fa) continue;
        dfs(y,x);
        for(reg j=0;j<p[x].size();++j){
        //    cout<<" j "<<p[x][j]<<endl;
            for(reg k=0;k<p[y].size();++k){
            //    cout<<" k "<<p[y][k]<<endl;
                if(p[x][j]==p[y][k]){
                    ans=max(ans,f[x][j]+f[y][k]);
                    f[x][j]=max(f[x][j],f[y][k]+1);
                }
            }
        }
    }
}
void div(int x,int id){
    for(reg i=2;(ll)i*i<=x;++i){
        if(x%i==0){
            p[id].push_back(i);
            f[id].push_back(1);
            while(x%i==0) x/=i;
        }
    }
    if(x>1){
        p[id].push_back(x);
        f[id].push_back(1);
    }
}
int main(){
    rd(n);int x;
    bool flag=false;
    for(reg i=1;i<=n;++i){
        rd(x);
        if(x!=1) flag=true;
        div(x,i);
    }
    if(!flag){
        puts("0");return 0;
    }
    ans=1;
    int y;
    for(reg i=1;i<=n-1;++i){
        rd(x);rd(y);
        add(x,y);add(y,x);
    }
    dfs(1,0);
    printf("%d",ans);
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2019/1/17 19:37:47
*/

总结:
其实有些时候,题目很麻烦

但是实际上可以简化条件,想想我们关心什么

原文地址:https://www.cnblogs.com/Miracevin/p/10284269.html

时间: 2024-08-30 14:54:56

CF1101D GCD Counting的相关文章

CF1101D GCD Counting 点分治+质因数分解

想到本质不同质因数不会很多就切了~ Code: #include <cstdio> #include <vector> #include <algorithm> #define N 200004 #define setIO(s) freopen(s".in","r",stdin) using namespace std; int n,tot,edges,sn,root,tl,answer; vector<int>v[N

CF EDU 1101D GCD Counting 树形DP + 质因子分解

CF EDU 1101D GCD Counting 题意 有一颗树,每个节点有一个值,问树上最长链的长度,要求链上的每个节点的GCD值大于1. 思路 由于每个数的质因子很少,题目的数据200000<2*3*5*7*11*13*17=510510.所以每个节点的质因子个数不多.那么树形DP的时候直接枚举每种因子即可. //#pragma GCC optimize(3) //#pragma comment(linker, "/STACK:102400000,102400000") /

CodeForces990G:GCD Counting(树分治+GCD)

You are given a tree consisting of nn vertices. A number is written on each vertex; the number on vertex ii is equal to aiai. Let's denote the function g(x,y)g(x,y) as the greatest common divisor of the numbers written on the vertices belonging to th

cf 990G GCD Counting (莫比乌斯反演 并查集)

990G 给你一棵树,问你有多少个点对(x,y)(x\(\leq\)y),使得(x,y)简单路径上的点权值的\(gcd\)为\(i\),对于\(i\in [1,200000]\)输出点对数目. 这题没有做出来,主要还是莫比乌斯反演时间太长不熟悉了.同时统计点对的技巧也自己没有想出来,实在是不应该. 我们设\(h(i)\)是有多少个点对(x,y)(x\(\leq\)y),使得(x,y)简单路径上的点权值的\(gcd\)为\(i\)的倍数的答案.于是有\(h(i)=\sum_{i=1}^{\lflo

educational codeforces round 58 (div2) D. GCD Counting

这道题每个节点都由子节点的不同状态转移过来,只要子节点可以整除这个节点的的某个质因子,就可以转移.为了遍历找到本节点的质因子对应于这个节点子节点的哪些状态,需要开个map<pair<int,int> ,int>来存储 #include<bits/stdc++.h> using namespace std; typedef pair<int,int> P; vector<int> G[200001]; vector<int> vec[2

口胡提交记录

为了偷懒提高刷题效率,有些题目只做口胡,并在此整理. 1.19 CF1101D GCD Counting pro:https://www.luogu.org/problemnew/show/CF1101D sol:https://www.cnblogs.com/Creed-qwq/p/10293719.html 原文地址:https://www.cnblogs.com/Creed-qwq/p/10293731.html

Educational Codeforces Round 58 (Rated for Div. 2) (题解)

C题卡了一个小时, 又被教育场教育了... A. Minimum Integer 大意:求不在$[l,r]$范围内的最小被$d$整除的数 模拟 #include <iostream> #define REP(i,a,n) for(int i=a;i<=n;++i) using namespace std; int main() { int t; scanf("%d", &t); REP(i,1,t) { int l,r,d; scanf("%d%d%

Educational Codeforces Round 58 (Rated for Div. 2)

A. Minimum Integer 水 #include<bits/stdc++.h> #define clr(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1e3+10; struct node{ ll num,mag; friend bool operator <(const node &a,const node &b){ return a.m

[Codeforces] [EducationalRound58] [1101] 瞎讲报告

目录 Educational Codeforces Round 58 (Rated for Div. 2) A. Minimum Integer B. Accordion C. Division and Union D.GCD Counting E.Polycarp's New Job F.Trucks and Cities G.(Zero XOR Subset)-less A,B,C,D,E都是几个月前写的..现在终于把这个坑填上了qwwwwq Educational Codeforces R