【Codeforces Round #694 (Div. 2)】D.Strange Definition

题意

给出 x , y x, y x,y相邻的定义:如果 l c m ( x , y ) g c d ( x , y ) \frac{lcm(x,y)}{gcd(x,y)} gcd(x,y)lcm(x,y) 是平方数,则称 x , y x, y x,y两个数相邻。
给出一个长度为 n n n的数列,每过一秒钟,数列中的每一个元素会被与它相邻的所有元素的乘积(包括它自身)所替换。
给出 q q q个询问,问在第 w i w_{i} wi秒时,当前数列中哪个元素有最多的相邻元素,不需要给出这个元素是谁,只要给出它的相邻元素个数。

题解

首先, l c m ( x , y ) = x ∗ y g c d ( x , y ) lcm(x, y) = \frac{x*y}{gcd(x,y)} lcm(x,y)=gcd(x,y)xy,得出 l c m ( x , y ) g c d ( x , y ) = x ∗ y g c d ( x , y ) 2 \frac{lcm(x,y)}{gcd(x,y)} = \frac{x*y}{gcd(x,y)^2} gcd(x,y)lcm(x,y)=gcd(x,y)2xy.
如果 x ∗ y g c d ( x , y ) 2 = z 2 \frac{x*y}{gcd(x,y)^2} = z^2 gcd(x,y)2xy=z2 是平方数, 则 x ∗ y = z 2 ∗ g c d ( x , y ) 2 x*y = z^2 * gcd(x,y)^2 xy=z2gcd(x,y)2也是平方数。也可知如果 x ∗ y x*y xy是平方数, x ∗ y g c d ( x , y ) 2 \frac{x*y}{gcd(x,y)^2} gcd(x,y)2xy也一定是平方数。
所以, l c m ( x , y ) g c d ( x , y ) \frac{lcm(x,y)}{gcd(x,y)} gcd(x,y)lcm(x,y) 是平方数当且仅当 x ∗ y x*y xy是平方数。
x ∗ y x*y xy是平方数,那么 x ∗ y x*y xy分解质因数后,每个质因数的指数必定是偶数,那么 x x x y y y分别分解质因数后其质因数的指数奇偶性必定相同。
也就是说,质因数的指数是多少已经不重要,只关心它们的奇偶性,那么就将指数模 2 2 2变成 0 0 0 1 1 1。将质因数指数 01 01 01相同的数分成一组,它们之间质因数的指数奇偶性都相同,也就互相相邻。这样就能统计某一时刻最多的相邻元素个数了。

下面考虑每一个时刻的情况是怎么样的。

可以发现如果一个组内元素个数是偶数,那么经过一秒后,它们的质因数指数都将变成 0 0 0(相乘时指数相加,偶数个1相加模2是0)。也就是说这样的组连同本来质因数指数就全是偶数的小组合成了一组。
如果组内元素个数是奇数,经过一秒后,它们的乘积的质因数指数将与它们完全一致(奇数个 1 1 1相加依然是奇数)。就是说它们不会改变。
那么就能得出结论, 1 1 1秒及之后的时间情况都是和 1 1 1秒的时候相同的,答案只要考虑 0 0 0秒和 1 1 1秒之后两种情况。
具体统计某个 01 01 01情况,可以将指数是奇数的质因数记录下来,如果两个数这些指数为 1 1 1的质因数相同,那么它们就是同一组的。
可以用将指数是奇数的质因数 h a s h hash hash记录,用 m a p map map维护每个 h a s h hash hash值有多少元素。具体见代码。

代码

/*
 * @file D.cpp
 * @path D:\code\ACM\codeforces\Div2_694\D.cpp
 * @author Xiuchen
 * @date  2021-01-06 00:06:22
*/

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<cmath>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<unordered_map>
//#define DEBUG
#define M_PI 3.14159265358979323846
#define dbg(x) cout << #x << " = "<< (x) << endl
#define dbg2(x1,x2) cout << #x1 << " = " << x1 << " " << #x2 << " = " << x2 << endl
#define dbg3(x1,x2,x3) cout<< #x1 << " = " << x1 << " " << #x2 << " = " << x2 << " " << #x3 << " = " << x3 <<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fLL;
const int maxn = 3e5 + 100;
const ll base = 19260817;
int gcd(int a, int b){
    return b ? gcd(b, a % b) : a;
}
int t, n;
int a[maxn];
map<ull, int> mp;
void fun(int x){
    ull tmp = 0;
    vector<int> v;
    for(int i = 2; i * i <= x; i++){
        if(x % i == 0){
            int cnt = 0;
            while(x % i == 0) cnt++, x /= i;
            if(cnt & 1) v.push_back(i);
        }
    }
    if(x > 1) v.push_back(x);
    for(auto &it : v) tmp = tmp * base + it;
    mp[tmp]++;
}
int main(){
#ifdef DEBUG
    freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif
    scanf("%d", &t);
    while(t--){
        mp.clear();
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%d", &a[i]);
            fun(a[i]);
        }
        int ansa = 0, ansb = 0;
        for(auto it = mp.begin(); it != mp.end(); it++){
            ansa = max(ansa, it->second);
            if((it->second) % 2 == 0 || it->first == 0) ansb += it->second;
        }
        ansb = max(ansa, ansb);
        int q;
        scanf("%d", &q);
        while(q--){
            ll w;
            scanf("%lld", &w);
            if(w == 0) printf("%d\n", ansa);
            else printf("%d\n", ansb);
        }
    }
    return 0;
}
  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值