题解:P10724 [GESP202406 七级] 区间乘积
前言
一个月没写题解了,为了挽救估值,精心写了这篇题解。
本文有些冗长,可能会浪费您的时间,但可以对这道题有更清晰的理解。
约定
- 下文中
\bigoplus 表示异或。 - 质数
p 在a 中出现了x 次表示将a 分解质因数后,p 一共出现了x 次。
思路
二进制表示
首先,我们把每个数
注意到本题
两数相乘的二进制表示
由于本题需要乘法,我们考虑当知道
容易发现,以上每种情况其实都是在进行异或操作,推出
本题主要部分
对于本题,令
容易发现,区间
令
细节
-
- 先计入答案,后更新(
ans += cnt[prexor]++;)。 -
- 十年 OI 一场空,不开 【】 见祖宗!
代码
#include <bits/stdc++.h>
using namespace std;
int n, a[100005], b[35], prexor;
long long ans, cnt[1 << 10];
vector <int> prime = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29};
void read(int &a, int ch = 0) {
while (!isdigit(ch = getchar()));
for (a = 0; isdigit(ch); ch = getchar()) a = (a << 3) + (a << 1) + (ch ^ 48);
}
void prework() {
// 预处理数组 b
for (int i = 1; i <= 30; i++) {
int j = i;
for (int k = 0; k < 10; k++) {
while (j % prime[k] == 0) {
b[i] ^= 1 << k;
j /= prime[k];
}
}
}
}
int main() {
prework();
read(n);
cnt[0] = 1;
for (int i = 1; i <= n; i++) {
read(a[i]);
prexor ^= b[a[i]];
ans += cnt[prexor]++;
}
cout << ans;
return 0;
}
写在最后
本题思维难度和代码难度都一般,感觉评绿有点高了,应该是上位黄。
本人表达能力较差,简单的思路被写得很冗长,但将其底层逻辑刨析得较为透彻。
本人写文章偏向学术,有些内容可能晦涩难懂,欢迎在评论区指出。