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

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
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:C马雯娟 返回首页