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[200001];
int dp[200001][10];
int a[200001];
int ans;
map<P,int> mp;
void dfs(int rt,int fa)
{
    int max1[10],max2[10];
    memset(max1,0,sizeof(max1));
    memset(max2,0,sizeof(max2));
    for(int i=0;i<vec[rt].size();i++)
    {
        int to=vec[rt][i];
        if(to==fa)
          continue;
        dfs(to,rt);
        for(int j=0;j<G[rt].size();j++)
        {
            int num=G[rt][j];
            if(a[to]%num==0)
            {
                int pos=mp[P(num,to)];
                int tmp=dp[to][pos];
                if(tmp>max1[j])
                {
                    max2[j]=max1[j];
                    max1[j]=tmp;
                }
                else if(tmp>max2[j])
                {
                    max2[j]=tmp;
                }
            }
        }
    }
    for(int i=0;i<G[rt].size();i++)
    {
        dp[rt][i]=1+max1[i];
        ans=max(ans,max1[i]+max2[i]+1);
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++)
    {
        int k=a[i];
        for(int j=2;j*j<=k;j++)
        {
            if(k%j==0)
            {
                G[i].push_back(j);
                mp[P(j,i)]=G[i].size()-1;
                while(k%j==0) k/=j;
            }
        }
        if(k>1)
        {
           G[i].push_back(k);
           mp[P(k,i)]=G[i].size()-1;
        }
    }
    for(int i=1;i<=n-1;i++)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        vec[x].push_back(y);
        vec[y].push_back(x);
    }
    dfs(1,-1);
    printf("%d\n",ans);
}

原文地址:https://www.cnblogs.com/lishengkangshidatiancai/p/10262357.html

时间: 2024-10-08 11:23:34

educational codeforces round 58 (div2) D. GCD Counting的相关文章

Educational Codeforces Round 58 (Rated for Div. 2)(待更新)

get人生第七场CF! 成绩:(exACM) rank AC3/7 Penalty104 rating() 题目:Educational Codeforces Round 58 (Rated for Div. 2) 错题题解: C. Division and Union 原文地址:https://www.cnblogs.com/xht37/p/10260260.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

Educational Codeforces Round 58 Div. 2 自闭记

明明多个几秒就能场上AK了.自闭. A:签到. #include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long char getc(){char c=getchar();while ((c<'A'

Educational Codeforces Round 74 #div2 ABCD

A. Prime Subtraction Description 给两个数$x,y,x \gt y$,判断$x-y$是否为一个素数的整数倍 Solution 由唯一分解可得每个大于1的数都可以唯一分解为素数幂次之积,显然只需要判断x-y是否大于1即可 1 #include <algorithm> 2 #include <cctype> 3 #include <cmath> 4 #include <cstdio> 5 #include <cstdlib&

【Educational Codeforces Round 35 D】Inversion Counting

[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 排列中交换任意两个数字. 排列的逆序对个数的奇偶性会发生变化. 翻转这个过程其实就是len/2对数字发生交换. 交换了偶数次的话,不变,否则奇偶性发生改变. 先暴力求出一开始的逆序对个数就好 [代码] #include <bits/stdc++.h> using namespace std; const int N = 1500; int n,a[N+10],cnt,now,m; void out(int x){ if (x=

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

感慨 这次比较昏迷最近算法有点飘,都在玩pygame...做出第一题让人hack了,第二题还昏迷想错了 A Minimum Integer(数学) 水题,上来就能做出来但是让人hack成了tle,所以要思考一下具体的过程 原本我是认为直接把d进行累加看什么时候不在那个segment内也就是那个范围之内结果tle 今天思考一下发现有两种情况 ①如果d本来就是小于左边界的那么就输出d就可以了,因为样例明确提示有原来的数也可以 ②然后就是如果d在范围之内或者范围外可以用余数来确定具体的数公式是: an

Educational Codeforces Round 21 G. Anthem of Berland(dp+kmp)

题目链接:Educational Codeforces Round 21 G. Anthem of Berland 题意: 给你两个字符串,第一个字符串包含问号,问号可以变成任意字符串. 问你第一个字符串最多包含多少个第二个字符串. 题解: 考虑dp[i][j],表示当前考虑到第一个串的第i位,已经匹配到第二个字符串的第j位. 这样的话复杂度为26*n*m*O(fail). fail可以用kmp进行预处理,将26个字母全部处理出来,这样复杂度就变成了26*n*m. 状态转移看代码(就是一个kmp

codeforces Round #250 (div2)

a题,就不说了吧 b题,直接从大到小排序1-limit的所有数的lowbit,再从大到小贪心组成sum就行了 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #define N 200000 6 using namespace std; 7 int pos[N],a[N],s[N],f[N],la[N],b[N],i,j,k,ans,n,p