牛客小白月赛60 E-寻找小竹!(数论)

链接:https://ac.nowcoder.com/acm/contest/45670/E
来源:牛客网

题目大意:

有n个城市,n-1条道路,每个城市都有它自己的优雅值ai

而如果两个相邻的路口的优雅值存在至少两个共同的质因子,那么就说这两个相邻的路口就是共同优雅的。

共同优雅联通块定义为:在城市中选取若干个路口,若这些路口们两两互相联通,且每两个相邻的路口都是共同优雅的,则该联通块称为共同优雅联通块。

问我们最大的共同优雅联通块里面包含了多少座城市?
输入
4
12 12 4 18
1 2
1 3
2 4
输出
3
说明
最大优雅联通块为 1,2,4三个路口所在的联通块,两两相邻的路口均包含 2,3 两个质因子。

有思路但是实现不好,唔,加练!

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<LL,LL> PII;
const LL MAXN=1e18;
const LL INF=1e9;
const LL N=5000200,M=2002;
LL primes[N],cnt=0;
bool st[N];
LL n,ans=0,a[N],sum[N];
//sum[i]记录当前节点i所包含的满足城市的数量
vector<LL> g[N];
//线性筛板子
void get_primes(LL n)
{
    for(LL i=2;i<=n;i++)
    {
        if(!st[i]) primes[cnt++]=i;
        for(LL j=0;primes[j]<=n/i;j++)
        {
            st[primes[j]*i]=true;
            if(i%primes[j]==0) break;
        }
    }
}
void dfs(LL u,LL fa)
{
    //每次遍历到一个点的时候,最少它就只有它自己一个点符合条件
    sum[u]=1;
    for(LL i=0;i<g[u].size();i++)
    {
        LL idx=g[u][i];
        if(idx==fa) continue;
        dfs(idx,u);

        //找到当前节点和父节点的共同最大公约数
        //这样就可以直接在gcd这个数字上寻找相同的质数因子
        LL gd=__gcd(a[u],a[idx]);
        LL num=0;
        for(LL i=0;i<cnt;i++)//在我们已经标记过的质因子上比对一下
        {
            if(gd==1) break;
            if(!st[gd])//这个质数存在,因为这就是个质数了,不可再分
            {
                num++;
                break;
            }
            if(gd%primes[i]==0)
            {
                num++;
                if(num>=2) break;
                while(gd%primes[i]==0)//约去相同质因子
                {
                    gd/=primes[i];
                }
            }
        }
        if(num>=2) sum[u]+=sum[idx];//达标:当前节点记录往下的子节点
    }
    ans=max(ans,sum[u]);
}
int main()
{
    cin.tie(0); cout.tie(0); ios::sync_with_stdio(false);
    LL T=1;
    //cin>>T;
    get_primes(5e6);//先获取数据范围内的所有质数
    while(T--)
    {
        cin>>n;
        for(LL i=1;i<=n;i++)
            cin>>a[i];
        for(LL i=1;i<n;i++)
        {
            LL x,y;
            cin>>x>>y;//建边
            g[x].push_back(y);
            g[y].push_back(x);
        }
        dfs(1,-1);//从根节点跑一跑
        cout<<ans<<endl;
    }
    return 0;
}
posted @ 2022-11-12 17:16  Vijurria  阅读(21)  评论(0编辑  收藏  举报