• 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;
    }
    
  • 相关阅读:
    HYSBZ 2818 gcd
    hdu1695 GCD
    HYSBZ 2301
    poj 2096
    正则表达式匹配HTML标签或标记
    [转载]Sed 命令详解 正则表达式元字符
    [转载]Shell删除各种注释的脚本
    [转载]sed实现直接修改文件内容
    [转载]强大的grep用法详解:grep与正则表达式
    [转载]【Shell脚本】逐行处理文本文件
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/14316596.html
Copyright © 2020-2023  润新知