题解 P4446 【[AHOI2018初中组]根式化简】
一道比较不错的数学思维题 。
本篇题解中可能有一些说的不太严谨的地方,望谅解,可以在评论区提出。
题目大意:
给出 n 个数,对于每一个数x,将其化简为
很良心的题面中提到了:
"如果你没有学过这部分数学知识,你可以认为题意是:给你
在这个式子中,我们不难发现
1.它是一个完全立方数
2.它不可化简为题面中的形式(不考虑可以化简为
证明如下:
如果此时的
所以我们在分离出小于等于
如果还有什么还有什么不懂的地方可以再结合代码里的注释理解一下。
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn = 1000005;
const int maxm = 31635;
int n, cnt;
int ans, tot;
int prime[maxm];
long long x;
long long p[maxn];
bool check[maxm];
long long read(void)
{
long long s = 0, w = 1;
char ch = getchar();
for(; ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') w = -1;
for(; ch <= '9' && ch >= '0'; ch = getchar()) s = s * 10 + ch - '0';
return s * w;
}
void Euler(int num) // 线性筛素数
{
check[1] = true;
for(int i = 2; i <= num; i++)
{
if(!check[i]) prime[++cnt] = i;
for(int j = 1; j <= cnt && i * prime[j] <= num; j++)
{
check[i * prime[j]] = true;
if(i % prime[j] == 0) break;
}
}
}
int main()
{
n = read();
for(register int i = 1; i <= maxn - 5; i++) p[i] = 1ll * i * i * i; // 完全立方数的预处理
Euler(maxm - 3); // 线性筛素数
for(; n; n--)
{
x = read();
ans = 1;
for(int i = 1; i <= cnt && prime[i] <= x; i++) // 枚举小于等于 x 的四分之一次方的素数来去除部分因子
{
for(; x % prime[i] == 0; )
{
x /= prime[i];
tot++;
if(tot == 3) // 如果这个因子的指数达到了 3 那么他可以对答案产生贡献
{
ans *= prime[i]; //算上这部分贡献
tot = 0; // 复原指数
}
}
tot = 0; // 复原指数
}
int pos = lower_bound(p + 1, p + maxn - 4, x) - p; // 二分查找小于等于它的最大的完全平方数
if(p[pos] == x) cout << ans * pos << '\n'; // 如果等于,即此时的 x 为一个完全平方数, 要加上它开立方后的贡献
else cout << ans << '\n'; // 否则没有贡献
}
return 0;
}
如果有什么疑问的话直接在评论区发或者洛谷私信均可。
谢谢阅读。