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];
int prime[N],is[N],num[N];
int val[N],hd[N],to[N<<1],nex[N<<1];
int size[N],mx[N],vis[N],f[N],g[N],tmp[N],depth[N],cur[N],number[N];
void add(int u,int v)
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
void getroot(int u,int ff)
{
    size[u]=1,mx[u]=0;
    for(int i=hd[u];i;i=nex[i])
        if(to[i]!=ff&&!vis[to[i]])
            getroot(to[i],u),size[u]+=size[to[i]],mx[u]=max(mx[u],size[to[i]]);
    mx[u]=max(mx[u],sn-size[u]);
    if(mx[u]<mx[root]) root=u;
}
void dfs(int u,int ff,int dep)
{
    number[u]=tmp[++tl]=__gcd(val[u],number[ff]),depth[tl]=dep;
    for(int i=hd[u];i;i=nex[i])
        if(to[i]!=ff&&!vis[to[i]])
            dfs(to[i],u,dep+1);
}
void calc(int u)
{
    int i,j,re;
    if(val[u]>1) answer=max(answer,1);
    tl=0;
    number[u]=val[u];
    for(i=hd[u];i;i=nex[i])
    {
        if(vis[to[i]]) continue;
        re=tl+1,dfs(to[i],u,1);
        for(j=re;j<=tl;++j)
        {
            int a=tmp[j],b=depth[j];
            if(a>1)
            {
                for(int k=0;k<v[a].size();++k)
                    g[v[a][k]]=max(g[v[a][k]],b),answer=max(answer,g[v[a][k]]+f[v[a][k]]+1);
            }
        }
        for(j=re;j<=tl;++j)
        {
            int a=tmp[j];
            if(a>1)
            {
                for(int k=0;k<v[a].size();++k) f[v[a][k]]=max(f[v[a][k]],g[v[a][k]]);
            }
        }
        for(j=re;j<=tl;++j)
        {
            int a=tmp[j];
            if(a>1) for(int k=0;k<v[a].size();++k) g[v[a][k]]=0;
        }
    }
    for(i=1;i<=tl;++i)
    {
        int a=tmp[i];
        if(a>1) for(j=0;j<v[a].size();++j) f[v[a][j]]=g[v[a][j]]=0;
    }
}
void solve(int u)
{
    vis[u]=1,calc(u);
    for(int i=hd[u];i;i=nex[i])
        if(!vis[to[i]])
            sn=size[to[i]],root=0,getroot(to[i],u),solve(root);
}
void init()
{
    int i,j;
    for(i=2;i<N;++i)
    {
        if(!is[i]) prime[++tot]=i;
        for(j=1;j<=tot&&i*prime[j]<N;++j)
        {
            is[i*prime[j]]=1;
            if(i%prime[j]==0) break;
        }
    }
    for(i=2;i<N;++i) num[i]=i;
    for(i=1;i<=tot;++i)
        for(j=prime[i];j<N;j+=prime[i])
        {
            v[j].push_back(prime[i]);
            while(num[j]%prime[i]==0) num[j]/=prime[i];
        }
}
int main()
{
    int i,j;
    init();
    // setIO("input");
    scanf("%d",&n);
    for(i=1;i<=n;++i) scanf("%d",&val[i]);
    for(i=1;i<n;++i)
    {
        int a,b;
        scanf("%d%d",&a,&b),add(a,b),add(b,a);
    }
    mx[root=0]=sn=n,getroot(1,0),solve(root);
    printf("%d\n",answer);
    return 0;
}

  

原文地址:https://www.cnblogs.com/guangheli/p/11477330.html

时间: 2024-10-10 00:14:50

CF1101D GCD Counting 点分治+质因数分解的相关文章

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的最长链 然后甚至可以暴力合并! 显然最优解可以被处理到! 代码: #incl

HDU 1695 GCD 欧拉函数+容斥原理+质因数分解

链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695 题意:在[a,b]中的x,在[c,d]中的y,求x与y的最大公约数为k的组合有多少.(a=1, a <= b <= 100000, c=1, c <= d <= 100000, 0 <= k <= 100000) 思路:因为x与y的最大公约数为k,所以xx=x/k与yy=y/k一定互质.要从a/k和b/k之中选择互质的数,枚举1~b/k,当选择的yy小于等于a/k时,可以

POJ 2429 GCD &amp; LCM Inverse (大数分解)

GCD & LCM Inverse 题目:http://poj.org/problem?id=2429 题意: 给你两个数的gcd和lcm,[1, 2^63).求a,b.使得a+b最小. 思路: lcm = a * b / gcd 将lcm/gcd之后进行大数分解,形成a^x1 * b^x2 * c^x3-- 的形式,其中a,b,c为互不相同的质数.然后暴力枚举即可. 代码: #include<map> #include<set> #include<queue>

Vijos P1786 质因数分解【暴力】

质因数分解 背景 NOIP2012普及组第一题 描述 已知正整数n是两个不同的质数的乘积试求出较大的那个质数. 格式 输入格式 输入只有一行包含一个正整数n. 输出格式 输出只有一行包含一个正整数p, 即较大的那个质数. 样例1 样例输入1 21 样例输出1 7 限制 1S 提示 [数据范围] 对于60%的数据,6 ≤ n ≤ 1000. 对于100%的数据,6 ≤ n ≤ 2*10的9次方 来源 NOIP2012普及组第一题 题目链接:https://vijos.org/p/1786 分析:大

POJ 2429 long long 质因数分解

GCD & LCM Inverse Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 16206   Accepted: 3008 Description Given two positive integers a and b, we can easily calculate the greatest common divisor (GCD) and the least common multiple (LCM) of a

质因数分解的rho以及miller-rabin

一.前言 质因数分解,是一个在算法竞赛里老生常谈的经典问题.我们在解决许多问题的时候需要用到质因数分解来辅助运算,而且质因数分解牵扯到许许多多经典高效的算法,例如miller-rabin判断素数算法,rho启发式搜索质因数分解算法等.在此文里,我要介绍的就是miller-rabin算法以及rho启发式搜索分解算法. 二.算术基本定理 首先,我们得知道,任意一个大于1的自然数都可以分解为有限个质数的乘积.这里因子均为质数,且为正整数.我们把这样的分解成为N的标准分解式.关于算数基本定理的应用有许多

浅谈质因数分解

浅谈质因数分解 ->part 1: 算数基本定理: 任何一个大于1的正整数都能唯一分解为有限个质数的乘积,可写作: \[N=\prod_{i=1}^m p_i^ {c_i}\] 其中\(c_i\)都是正整数,\(p_i\)都是质数,且满足\(p_1<p_2<-<p_m\) ->part 2: 分解方法: 试除法 结合质数判定的"试除法"和质数筛选的"\(Eratosthenes\) 筛法",我们可以扫描 \(2-\sqrt N\)的每个

快速质因数分解及素性测试&amp;ABC142D

首先,这个整数的标准分解非常的显然易见对吧: 一般我们要把一个数分解成这个样子我们可以这样写: 1 #include<cstdio> 2 int p[105],w[105],k; 3 void factorize(int n) 4 { 5 for(int i=2;i*i<=n;i++) 6 if(n%i==0) 7 { 8 p[++k]=i; 9 while(n%i==0) 10 n/=i,w[k]++; 11 } 12 if(n!=1) 13 p[++k]=n,w[k]=1; 14 }

【BZOJ2227】【ZJOI2011】看电影 [组合数学][质因数分解]

看电影 Time Limit: 10 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 到了难得的假期,小白班上组织大家去看电影.但由于假期里看电影的人太多,很难做到让全班看上同一场电影,最后大家在一个偏僻的小胡同里找到了一家电影院.但这家电影院分配座位的方式很特殊,具体方式如下: 1. 电影院的座位共有K个,并被标号为1…K,每个人买完票后会被随机指定一个座位,具体来说是从1…K中等可能的随机选取一个正整数,设其为L.