CF1470B-Strange Definition

题意

给出 (n) 个数,满足 (frac{lcm(x,y)}{gcd(x,y)}) 为完全平方数的 (x,y) 称为相邻的。在每一秒,会发生以下操作:

  • 每个数被所有和自己相邻数字(包括自己)的乘积所替换
  • (d_i) 为和数字 (a_i) 相邻的数字(包括自己)的数量

给出 (q) 组询问,查询第 (w) 秒时,数组中最大的 (d_i)

题目链接:https://codeforces.com/contest/1470/problem/B

分析

因为:

[lcm(x,y)=frac{x*y}{gcd(x,y)} ]

有:

[frac{lcm(x,y)}{gcd(x,y)}=frac{x*y}{gcd(x,y)^2} ]

因此,要使得 (frac{lcm(x,y)}{gcd(x,y)}) 为完全平方数,那么必然有 (x*y) 为完全平方数,即 (x*y) 的质因子的幂均为偶数。对所有数的质因子的幂进行模 (2) 的操作,假设 (x) 的一个质因子及其幂为 (p_i^{alpha_i}) 。可以发现,如果 (x)(y) 的乘积为完全平方数,那么 (x)(y) 的相同质因子的幂应该是相同的(模 (2) 情况下),因为偶数+偶数=偶数、奇数+奇数=偶数。因此,每个数可以用其幂模 (2) 后质因子的乘积代替,即 (x=p_1^{alpha_i\%2}*cdots *p_k^{alpha_k\%2}) 。 那么,在初始时刻,只要转化后的数相同,二者的乘积即为完全平方数,计数即可。在 (1s) 时,会有一个转化,即如果一个数出现了偶数次,那么这个数的各个质因子的幂会转化为 (0) 。此时重新计数,求出最大的 (d_i) ,即为 (1s) 及之后的答案。

代码

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
const int N=1e6+5;
const int M=1e5;
int n,cnt;
int prime[M];
bool vis[N];
map<ll,int>mp;
vector<ll>num;
void init()
{
    cnt=0;
    int maxn=1e6;
    for(int i=2;i<=maxn;i++)
    {
        if(!vis[i])
            prime[++cnt]=i;
        for(int j=1;j<=cnt&&i*prime[j]<=maxn;j++)
        {
            vis[prime[j]*i]=1;
            if(i%prime[j]==0)
                break;
        }
    }
}
void devide(int x)
{
    ll res=1;
    for(int i=1;i<=cnt&&1LL*prime[i]*prime[i]<=x;i++)
    {
        int cot=0;
        while(x%prime[i]==0)
        {
            x/=prime[i];
            cot++;
        }
        if(cot&1) res*=prime[i];
    }
    if(x>1)
        res*=x;
    num.pb(res);
    mp[res]++;
}
int main()
{
    int t;
    init();
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        num.clear();
        mp.clear();
        for(int i=1;i<=n;i++)
        {
            int a;
            scanf("%d",&a);
            devide(a);
        }
        int q,ans1=0,ans2=0;
        ll w;
        for(int i=0;i<num.size();i++)
            ans1=max(ans1,mp[num[i]]);
        for(int i=0;i<num.size();i++)
        {
            if(mp[num[i]]%2==0||num[i]==1)
            {
                ans2+=mp[num[i]];
                mp[num[i]]=0;
            }
        }
        ans2=max(ans2,ans1);
        scanf("%d",&q);
        while(q--)
        {
            scanf("%lld",&w);
            if(w==0) printf("%d
",ans1);
            else printf("%d
",ans2);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/1024-xzx/p/14316596.html