2019 Multi-University Training Contest 4 - Minimal Power of Prime

乱搞

先把\(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 <bits/stdc++.h>
 #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 <typename A, typename B, typename C>
 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<int> 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;
 }
}

猜你喜欢

转载自www.cnblogs.com/onionQAQ/p/11280485.html