[AHOI 2018初中组] 根式化简 题解

**[AHOI 2018初中组] 根式化简 题解 **

好了告诉你们其实这就是一题非常简单的数论……

先考虑最暴力的算法

首先可以明了的一点就是如果我们把一个数 \(N\) 表示成 \(x=k*a^3\) 的形式,那么 \(k\) 一定满足 \(k ≤ \sqrt[3]{N}\)

所以我们可以暴力枚举 \(1- \sqrt[3]{N}\) 的每一个数 \(x\),只要满足 \(x | N\) ,我们就判断 \(N/x\)是否为立方数,这些立方数可以在 \(\sqrt[3]{N}\)的时间内预处理出来。

我们看看数据范围,好的你已经 \(get\) \(1-4\) 个测试点,也就是 \(40\) 分了。

有没有优化?

我们注意到 \(5,6\) 两个特殊数据点:\(x\) 为立方数,这启示我们可以二分处理掉这一部分数据。

很明显若 \(i\) 是递增的,那么 \(i^3\) 也是递增的,所以答案具有单调性。

并且 \(\sqrt[4]{N} ≤ \sqrt[3]{N} ≤ \sqrt{N}\) ,所以二分下界 $ \sqrt{N}$,上界不好取,取 \(\sqrt[3]{10^{18}}=10^6\) 即可。

按照数据打程序,你已经可以通过 \(1-6\) 个测试点了。\(60\) 分在没想到正解的时候还是很可观的。

总结启示,得到正解

你知道 \(N=k*a^3\) ,那么应该会有:\(k,a≤\sqrt[3]{N}\) 对吧?那么我们肯定不能暴力对 \(N\) 质因数分解,所以我们想想这些因数在什么范围内才是我们所要的?最简单的上界也是很容易想到的:\(\sqrt[3]{N}\)。看一眼数据,唔!又过了两个点\(QAQ\)

单着并不是我们要的,我们在期望正解。很显然 \(\sqrt[3]{N}\) 这个上界还是太大,因此我们需要观察还有没有更小的上界。其实我们发现可以把上界缩小到 \(\sqrt[4]{N}\),然后$ \forall i∈[1,\sqrt[4]{N}],\text{且}i∈prime,i\mid N $,把 \(N\)\(i\) 全部除去,并且只要除的次数每逢 \(3\) 的倍数就把 \(ans\) 累乘上 \(i\)

为什么这样可行?这么做极有可能剩下一个较大的 \(k\) 还可以继续分解啊?

其实是不可能的,如果剩下除完了的 \(N\) 还能继续分解成上面那种形式的话,那么它早就被 \([2,\sqrt[4]{N}]\) 内的质因子除掉了,除非剩下了一个立方数。

所以我们再次利用二分判断剩下的除完的那个 \(N\) 还是不是立方数就好了,如果是累乘上 \(\sqrt[3]{N}\)

接下来根据代码来理解思路吧:

#include<bits/stdc++.h>
using namespace std;

const int N = 4e4 + 10;
const int M = 1e6 + 10;

#define ll long long
int prime[M]; bool v[M]; 

int Prime(int n) {
	int m = 0;
	v[0] = v[1] = 1;
	for(int i = 2; i <= n; i++) {
		if(v[i] == 0) prime[++m] = i;
		for(int j = 1; j <= m && prime[j] <= n / i; j++) {
			v[i * prime[j]] = 1;
			if(i % prime[j] == 0) break;	
		}
	}
	return m;
}

ll p[M];
int main() {
	// 预处理立方根 
	for(int i = 1; i <= M; i++) p[i] = (ll) i * i * i; 
	// 预处理质数 
	int m = Prime(N), T; ll x, ans = 1;
	scanf("%d", &T);
	while(T--) {
		scanf("%lld", &x);
		// 在 1-x^(1/4) 内枚举因子 
		for(int i = 1, cnt = 0; i <= m && p[i] <= x; i++, cnt = 0) 
			while(x % prime[i] == 0) {
				cnt++, x /= prime[i];
				if(cnt % 3 == 0) ans *= prime[i];
			}
		// 特判剩下的数 
		ll k = lower_bound(p + 1, p + M + 1, x) - p;
		if(k * k * k == x) ans *= k;
		printf("%lld\n", ans);
		ans = 1;
	}
	return 0;
}
posted @ 2019-09-24 21:13  Ning-H  阅读(218)  评论(0编辑  收藏  举报