Codeforces1470 B. Strange Definition(数论)

题意:

在这里插入图片描述
数据范围:n<=3e5,a(i)<=1e6,q<=3e5,w<=1e18

解法:

l c m ( x , y ) g c d ( x , y ) = x y g c d ( x , y ) 2 x y g c d ( x , y ) 2 = x g c d ( x , y ) y g c d ( x , y ) 要 使 得 上 式 结 果 是 完 全 平 方 数 , 需 要 x 和 y 去 掉 g c d 部 分 后 相 乘 为 完 全 平 方 数 . 发 现 x 个 y 各 自 的 偶 数 次 幂 质 因 子 也 可 以 去 掉 , 不 影 响 相 乘 结 果 , 设 f ( x ) = x 去 掉 偶 数 次 幂 质 因 子 之 后 的 值 , 如 果 x 和 y 是 相 关 的 , 那 么 一 定 f ( x ) = f ( y ) . 考 虑 每 秒 钟 f ( x ) 会 如 何 变 换 : 发 现 当 f ( x ) 值 的 数 量 为 偶 数 个 的 时 候 , x 的 f ( x ) 会 变 成 1 ( 因 为 相 乘 之 后 幂 次 变 成 偶 数 次 , 会 被 去 掉 ) . 当 f ( x ) 值 的 数 量 为 奇 数 个 的 时 候 , x 的 f ( x ) 不 会 变 ( 因 为 偶 数 次 的 会 变 成 0 , 只 剩 下 一 个 ) . 变 一 次 之 后 只 剩 下 1 和 某 些 孤 立 的 f ( x ) , 之 后 不 会 再 变 了 . 因 此 只 需 要 计 算 出 t = 0 和 t = 1 时 候 的 f ( x ) 即 可 , 统 计 答 案 就 是 对 按 f ( x ) 计 数 . \frac {lcm(x,y)}{gcd(x,y)}=\frac{xy}{gcd(x,y)^2}\\ \frac{xy}{gcd(x,y)^2}=\frac{x}{gcd(x,y)}\frac{y}{gcd(x,y)}\\ 要使得上式结果是完全平方数,需要x和y去掉gcd部分后相乘为完全平方数.\\ 发现x个y各自的偶数次幂质因子也可以去掉,不影响相乘结果,\\ 设f(x)=x去掉偶数次幂质因子之后的值,\\ 如果x和y是相关的,那么一定f(x)=f(y).\\ 考虑每秒钟f(x)会如何变换:\\ 发现当f(x)值的数量为偶数个的时候,\\ x的f(x)会变成1(因为相乘之后幂次变成偶数次,会被去掉).\\ 当f(x)值的数量为奇数个的时候,\\ x的f(x)不会变(因为偶数次的会变成0,只剩下一个).\\ 变一次之后只剩下1和某些孤立的f(x),之后不会再变了.\\ 因此只需要计算出t=0和t=1时候的f(x)即可,\\ 统计答案就是对按f(x)计数. gcd(x,y)lcm(x,y)=gcd(x,y)2xygcd(x,y)2xy=gcd(x,y)xgcd(x,y)y使,xygcd.xy,,f(x)=x,xy,f(x)=f(y).f(x):f(x),xf(x)1(,).f(x),xf(x)(0,).1f(x),.t=0t=1f(x),f(x).

code:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxm=1e6+5;
int np[maxm];
int prime[maxm],cnt;
int a[maxm];
int f[maxm];
int n,q;
void init(){
    for(int i=2;i<maxm;i++){
        if(!np[i]){
            prime[cnt++]=i;
        }
        for(int j=0;j<cnt;j++){
            if(prime[j]*i>=maxm)break;
            np[prime[i]*j]=1;
            if(i%prime[j]==0)break;
        }
    }
}
void solve(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=n;i++)f[i]=1;
    for(int i=1;i<=n;i++){
        int x=a[i];
        for(int j=0;j<cnt&&prime[j]*prime[j]<=x;j++){
            if(x%prime[j]==0){
                int cc=0;
                while(x%prime[j]==0)x/=prime[j],cc^=1;
                if(cc){
                    f[i]*=prime[j];
                }
            }
        }
        if(x!=1)f[i]*=x;
    }
    int ans0=0;
    int ans1=0;
    //计算t=0时的答案
    map<int,int>num0;
    for(int i=1;i<=n;i++){
        num0[f[i]]++;
    }
    for(auto i:num0){
        ans0=max(ans0,i.second);
    }
    //计算t=1时的答案
    map<int,int>num1;
    for(int i=1;i<=n;i++){
        if(num0[f[i]]%2==0){
            f[i]=1;
        }
        num1[f[i]]++;
    }
    for(auto i:num1){
        ans1=max(ans1,i.second);
    }
    //
    scanf("%d",&q);
    while(q--){
        ll w;scanf("%lld",&w);
        if(w==0)printf("%d\n",ans0);
        else printf("%d\n",ans1);
    }
}
signed main(){
    init();
    int T;cin>>T;
    while(T--){
        solve();
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值