Codeforces-1471 D. Strange Definition(哈希,质因数分解)

23 篇文章 0 订阅
17 篇文章 0 订阅

Let us call two integers 𝑥 and 𝑦 adjacent if 𝑙𝑐𝑚(𝑥,𝑦)𝑔𝑐𝑑(𝑥,𝑦) is a perfect square. For example, 3 and 12 are adjacent, but 6 and 9 are not.

Here 𝑔𝑐𝑑(𝑥,𝑦) denotes the greatest common divisor (GCD) of integers 𝑥 and 𝑦, and 𝑙𝑐𝑚(𝑥,𝑦) denotes the least common multiple (LCM) of integers 𝑥 and 𝑦.

You are given an array 𝑎 of length 𝑛. Each second the following happens: each element 𝑎𝑖 of the array is replaced by the product of all elements of the array (including itself), that are adjacent to the current value.

Let 𝑑𝑖 be the number of adjacent elements to 𝑎𝑖 (including 𝑎𝑖 itself). The beauty of the array is defined as max1≤𝑖≤𝑛𝑑𝑖.

You are given 𝑞 queries: each query is described by an integer 𝑤, and you have to output the beauty of the array after 𝑤 seconds.

Input
The first input line contains a single integer 𝑡 (1≤𝑡≤105) — the number of test cases.

The first line of each test case contains a single integer 𝑛 (1≤𝑛≤3⋅105) — the length of the array.

The following line contains 𝑛 integers 𝑎1,…,𝑎𝑛 (1≤𝑎𝑖≤106) — array elements.

The next line contain a single integer 𝑞 (1≤𝑞≤3⋅105) — the number of queries.

The following 𝑞 lines contain a single integer 𝑤 each (0≤𝑤≤1018) — the queries themselves.

It is guaranteed that the sum of values 𝑛 over all test cases does not exceed 3⋅105, and the sum of values 𝑞 over all test cases does not exceed 3⋅105
Output
For each query output a single integer — the beauty of the array at the corresponding moment.

Example
inputCopy
2
4
6 8 4 2
1
0
6
12 3 20 5 80 1
1
1
outputCopy
2
3
Note
In the first test case, the initial array contains elements [6,8,4,2]. Element 𝑎4=2 in this array is adjacent to 𝑎4=2 (since 𝑙𝑐𝑚(2,2)𝑔𝑐𝑑(2,2)=22=1=12) and 𝑎2=8 (since 𝑙𝑐𝑚(8,2)𝑔𝑐𝑑(8,2)=82=4=22). Hence, 𝑑4=2, and this is the maximal possible value 𝑑𝑖 in this array.

In the second test case, the initial array contains elements [12,3,20,5,80,1]. The elements adjacent to 12 are {12,3}, the elements adjacent to 3 are {12,3}, the elements adjacent to 20 are {20,5,80}, the elements adjacent to 5 are {20,5,80}, the elements adjacent to 80 are {20,5,80}, the elements adjacent to 1 are {1}. After one second, the array is transformed into [36,36,8000,8000,8000,1].

题意:
两个数 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)是完全平方数的时候。每过一秒,每个数就变成所有与其相邻数(包括自己)的成绩。定义 d [ i ] d[i] d[i]代表与第 i i i个数相邻数的个数。
每次询问给出 w w w,代表 w w w秒后最大的 d [ i ] d[i] d[i]

思路:
很巧妙的一道题。

很明显题意等价于 x ∗ y x*y xy是完全平方数,也就是 x , y x,y x,y对于质因数的次幂奇偶性相同。所以我们只需要考虑每个数质因数的奇偶性,可以用哈希存下每个数质因数次幂为奇数的部分,然后就可以统计个数了。

第一秒以及之后,如果一个数对应相邻数为偶数,那么其所有质因子都会变成偶数次幂,否则不变。所以只需要考虑第0秒和第一秒。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
#include <unordered_map>
#include <vector>
using namespace std;

typedef long long ll;
typedef unsigned long long ull;
const int maxn = 3e5 + 7;
const int base = 1e9 + 7;
int a[maxn];
ull b[maxn];
unordered_map<ull,int>mp1,mp2;
void func(int id,int x,int flag) {
    if(flag == 1) {
        ull tmp = b[id];
        int now = (mp1[tmp] & 1);
        if(now == 0) {
            tmp = 0;
        }
        mp2[tmp]++;
        return;
    }
    vector<int>vec;
    for(int i = 2;i <= sqrt(x);i++) {
        int cnt = 0;
        while(x % i == 0) {
            x /= i;cnt++;
        }
        if(cnt & 1) {
            vec.push_back(i);
        }
    }
    if(x > 1) vec.push_back(x);
    ull tmp = 0;
    for(int i = 0;i < vec.size();i++) {
        tmp = tmp * base + vec[i];
    }
    mp1[tmp]++;
    b[id] = tmp;
}

int main() {
    int T;scanf("%d",&T);
    while(T--) {
        int n;scanf("%d",&n);
        mp1.clear();mp2.clear();
        for(int i = 1;i <= n;i++) {
            scanf("%d",&a[i]);
            func(i,a[i],0);
        }
        int mx1 = 0,mx2 = 0;
        for(auto it:mp1) {
            mx1 = max(mx1,it.second);
        }
        for(int i = 1;i <= n;i++) {
            func(i,a[i],1);
        }
        for(auto it:mp2) {
            mx2 = max(mx2,it.second);
        }
        int q;scanf("%d",&q);
        for(int i = 1;i <= q;i++) {
            int que;scanf("%d",&que);
            if(que == 0) {
                printf("%d\n",mx1);
            } else {
                printf("%d\n",mx2);
            }
        }
    }
    return 0;
}
//18000
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值