Strange Definition

Strange Definition

Created by LXC on Wed May 17 09:09:21 2023

https://codeforces.com/problemset/problem/1470/B

ranting: 1900

tag: bitmasks, graphs, hashing, math, number theory

题意

定义两个数x和y相邻,则满足lcm(x,y)/gcd(x,y)是一个平方数。

现在给出一个数组a

定义$d_i$为$a_i$的相邻的个数。而所有$d_i$中的最大值是数组的美丽值。

每一秒钟,每个元素$a_i$会变为所有与$a_i$相邻的数(包含自身)的乘积。

现在有q次查询,每次查询都要求第i秒时的美丽值。

题解

根据唯一分解定理,每个正整数都可以分解为质数的乘积。设$p_i$是第$i$个质数。
设$x = p_1^{\alpha_1}p_2^{\alpha_2}\cdots p_n^{\alpha_n}, y = p_1^{\beta_1}p_2^{\beta_2}\cdots p_n^{\beta_n},$

$lcm(x,y) = p_1^{max(\alpha_1, \beta_1)}p_2^{max(\alpha_2, \beta_2)}\cdots p_n^{max(\alpha_n, \beta_n)}$

$gcd(x,y) = p_1^{min(\alpha_1, \beta_1)}p_2^{min(\alpha_2, \beta_2)}\cdots p_n^{min(\alpha_n, \beta_n)}$

$lcm(x,y)/gcd(x,y) = p_1^{max(\alpha_1, \beta_1)-min(\alpha_1, \beta_1)}p_2^{max(\alpha_2, \beta_2)-min(\alpha_2, \beta_2)}\cdots p_n^{max(\alpha_n, \beta_n)-min(\alpha_n, \beta_n)} = p_1^{|\alpha_1-\beta_1|}p_2^{|\alpha_2-\beta_2|}\cdots p_n^{|\alpha_n-\beta_n|}$

如果$lcm(x,y)/gcd(x,y)$是平方数,则说明x和y对应质因子指数奇偶性相同。即$\alpha_i \equiv \beta_i \pmod 2$

那么我们可以对a数组进行处理,得到数组b。

对于每个$a_i$分解质因数。当同一个质因数出现偶数次则不计入,若$a_i = p_1^{\alpha_1}p_2^{\alpha_2}\cdots p_n^{\alpha_n}$则$b_i = p_1^{\alpha_1\mod 2}p_2^{\alpha_2\mod 2}\cdots p_n^{\alpha_n\mod 2}$。

在0秒的时候,b数组中每个数出现的次数其实就是这个数的相邻的个数。所以b中最大的重复值个数就是0秒时的答案。

那么在非0秒时,b中重复个数为非1的奇数,它们各自相邻的个数不会变化。所以统计重复个数为非1的奇数的最大值mx。对于出现次数为偶数可以全部变为1。所有偶数和1的个数之和与mx的最大值就是答案。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

#include <bits/stdc++.h>
// #define LOCAL
// #define SINGLE_INPUT
#define ll long long
#define ull unsigned long long
#define N 1000005
#define MOD 998244353
using namespace std;

vector<int> p;
int lpf[N];

void sieve() {
lpf[1] = 1;
for (int i = 2; i < N; i++) {
if (lpf[i] == 0) {
lpf[i] = i;
p.push_back(i);
}
for (int j = 0; p[j] * i < N; j++) {
lpf[p[j] * i] = p[j];
if (i % p[j] == 0) {
break;
}
}
}
// for (int i : p) {
// cout << i << "\n";
// }
// for (int i = 1; i < N; i++) {
// cout << i << " " << lpf[i] << "\n";
// }
}

void sol() {
map<int, int> mp;
int n;
cin >> n;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
int fac = 1;
while (lpf[x] != 1) {
if (fac % lpf[x])
fac *= lpf[x];
else
fac /= lpf[x];
x /= lpf[x];
}
mp[fac]++;
}
int ans0 = 0, ans1 = 0, mx = 0;
for (auto [i, j] : mp) {
// cout << i << "--" << j << ", ";
ans0 = max(ans0, j);
if (i == 1 || j % 2 == 0)
ans1 += j;
else
mx = max(mx, j);
}
ans1 = max(ans1, mx);
// cout << "\n";
int q;
cin >> q;
while (q--) {
ll w;
cin >> w;
cout << (w ? ans1 : ans0) << "\n";
}
}

int main() {
sieve();
#ifdef LOCAL
auto start_time = clock();
cerr << setprecision(3) << fixed;
#endif
cout << setprecision(15) << fixed;
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifndef SINGLE_INPUT
int t;
cin >> t;
while (t--) {
sol();
}
#else
sol();
#endif
#ifdef LOCAL
auto end_time = clock();
cerr << "Execution time: "
<< (end_time - start_time) * (int)1e3 / CLOCKS_PER_SEC << " ms\n";
#endif
return 0;
}