乱搞
先把\(N^\frac{1}{5}\)的质数筛出来
然后在把这些质数分解,最后剩下的如果是1,就可以直接出答案了。
如果不是1,可以想到剩下的这个数不会超过某个数的4次方,因为那样就超过1e18了
所以考虑影响答案的情况,这个数可以拆成 p^4, p^3, p^2, p^2*q^2,其中p和q都是质数,且不在我们筛的范围内。
那么我们可以把剩下的这个数直接开方,因为pow的精度损失,我们取前后5的范围再把他给乘回去。
如果能够乘回到开方之前,表示是这个数可以开成这个次方,继续更新答案即可,如果4 3 2 都不能开方,拿答案就是1了,表示它本身就是个大质数。
#include#define INF 0x3f3f3f3f #define full(a, b) memset(a, b, sizeof a) #define __fastIn ios::sync_with_stdio(false), cin.tie(0) #define pb push_back using namespace std; typedef long long LL; inline int lowbit(int x){ return x & (-x); } inline LL read(){ LL ret = 0, w = 0; char ch = 0; while(!isdigit(ch)){ w |= ch == '-', ch = getchar(); } while(isdigit(ch)){ ret = (ret << 3) + (ret << 1) + (ch ^ 48); ch = getchar(); } return w ? -ret : ret; } inline int lcm(int a, int b){ return a / __gcd(a, b) * b; } template inline A fpow(A x, B p, C lyd){ A ans = 1; for(; p; p >>= 1, x = 1LL * x * x % lyd)if(p & 1)ans = 1LL * x * ans % lyd; return ans; } const int N = 4005; int _; LL n; bool vis[N]; vector p; inline void calc(){ for(int i = 2; i <= N - 5; i ++){ if(!vis[i]) p.pb(i); for(int j = 0; j < p.size() && p[j] * i <= N - 5; j ++){ vis[p[j] * i] = true; if(i % p[j] == 0) break; } } } inline LL f(LL a, int b){ LL ret = 1; while(b --) ret *= a; return ret; } inline bool solve(LL a, int p){ LL t = pow(a, 1.0 / p) + 1; t -= 5; if(t < 1) t = 1; while(f(t + 1, p) <= a) t ++; return f(t, p) == a; } int main(){ //freopen("data.txt", "r", stdin); calc(); for(_ = read(); _; _ --){ n = read(); int ret = INF; for(int i = 0; i < p.size() && p[i] <= n; i ++){ if(n % p[i] == 0){ int cnt = 0; while(n % p[i] == 0) cnt ++, n /= p[i]; ret = min(ret, cnt); } } if(n == 1) printf("%d\n", ret); else{ bool flag = false; for(int i = 4; i >= 2; i --){ if(solve(n, i)){ flag = true; ret = min(ret, i); break; } } if(!flag) printf("1\n"); else printf("%d\n", ret); } } return 0; }}