AT_abc400_e [ABC400E] Ringo‘s Favorite Numbers 3 题解
题目传送门
题目大意
题目描述
对于正整数 N N N,当且仅当满足以下两个条件时, N N N 被称为 400 number:
- N N N 恰好有 2 2 2 种不同的素因数。
- 对于 N N N 的每个素因数 p p p, N N N 被 p p p 整除的次数为偶数次。更严格地说,对于 N N N 的每个素因数 p p p,使得 p k p^k pk 是 N N N 的约数的最大非负整数 k k k 是偶数。
给定 Q Q Q 个查询,请回答每个查询。每个查询给出一个整数 A A A,请找出不超过 A A A 的最大 400 number 的值。在本问题的约束条件下,保证 A A A 以下必定存在至少一个 400 number。
输入格式
输入通过标准输入给出,格式如下:
Q Q Q
query 1 \text{query}_1 query1
query 2 \text{query}_2 query2
⋮ \vdots ⋮
query Q \text{query}_Q queryQ
其中, query i \text{query}_i queryi 表示第 i i i 个查询,格式为:
A A A
输出格式
输出 Q Q Q 行。第 i i i 行应输出第 i i i 个查询的答案。
输入输出样例 #1
输入 #1
5
404
36
60
1000000000000
123456789
输出 #1
400
36
36
1000000000000
123454321
说明/提示
约束条件
- 1 ≤ Q ≤ 2 × 1 0 5 1 \leq Q \leq 2 \times 10^5 1≤Q≤2×105
- 对于每个查询, 36 ≤ A ≤ 1 0 12 36 \leq A \leq 10^{12} 36≤A≤1012
- 输入中的所有值均为整数
样例解释 1
以第一个查询为例:
400
400
400 的素因数恰好为
2
2
2 和
5
5
5 两种。
400
400
400 被
2
2
2 整除的次数为
4
4
4 次(偶数次),被
5
5
5 整除的次数为
2
2
2 次(偶数次),因此
400
400
400 是 400 number。而
401
401
401、
402
402
402、
403
403
403、
404
404
404 均不是 400 number,故答案为
400
400
400。
翻译由 DeepSeek R1 完成
解题思路
我们使用筛法筛出所有素数并打上标记,然后再跑一遍,计算每个数 x x x 的质因子个数,如果为 2 2 2,那么 x 2 x^2 x2 就是满足题意的一个解,把他存起来。
对于每次询问 A A A,我们只需要找到未超过 ⌊ A ⌋ \lfloor\sqrt{A}\rfloor ⌊A⌋ 的最大的只有两个质因子的数 k k k,那么直接输出 k 2 k^2 k2 即可。
时间复杂度约为 O ( n ) \mathcal{O}(\sqrt{n}) O(n)。
只不过这里的筛法就不需要欧拉筛了,直接上埃拉托斯特尼筛法(埃氏筛法)就行,感觉实现方面还简单一些。
CODE:
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6 + 10;
int cnt[N], ans[N];
bool isprime[N];
inline void shai() {
for (int i = 2; i <= 1e6; ++i) {
if (!isprime[i]) {
for (int j = i + i; j <= 1e6; j += i) {
isprime[j] = true;
}
}
}
for (int i = 2; i <= 1e6; ++i)
if (!isprime[i]) {
for (int j = i; j <= 1e6; j += i) {
cnt[j]++;
}
}
for (int i = 6; i <= 1e6; ++i) {
if (cnt[i] == 2) {
ans[i] = i;
} else {
ans[i] = ans[i - 1];
}
}
}
signed main() {
ios::sync_with_stdio(false);
ios_base::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
shai();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
n = ans[(int)sqrtl(n)];
cout << n * n << "\n";
}
return 0;
}