2019 Multi-University Training Contest 4 1010 | HDU 6623 Minimal Power of Prime

Problem Description

You are given a positive integer n > 1. Consider all the different prime divisors of n. Each of them is included in the expansion n into prime factors in some degree. Required to find among the indicators of these powers is minimal.

Input

The first line of the input file is given a positive integer T ≤ 50000, number of positive integers n in the file. In the next T line sets these numbers themselves. It is guaranteed that each of them does not exceed 10^18.

Output

For each positive integer n from an input file output in a separate line a minimum degree of occurrence of a prime in the decomposition of n into simple factors.

Sample Input

5
2
12
108
36
65536

Sample Output

1
1
2
2
16

Source
2019 Multi-University Training Contest 4

Brief Description

找出一个数(<1e18)的因式分解式中最小的幂

例如 360 = 2^3 * 3^2 * 5^1

则输出1


训练的时候,一开始先想到将所有因子求出来,TLE
想到先把maxn开4次方来做,再TLE
怎么就没有想到开5次方呢,,,只需改三行代码就过了…
被自己蠢到。。

而且好像要加上快读才能过 不然也T 时间卡的有点死

Solution

Let’s first factorize N using prime numbers not larger than N1/5. And let’s denote M as the left part, all the prime factors of M are larger than N1/5. If M=1 then we are done, otherwise M can only be P2, P3, P4 or P2Q2, here P and Q are prime numbers.
(1) If M1/4 is an integer, we can know that M=P4. Update answer using 4 and return.
(2) If M1/3 is an integer, we can know that M=P3. Update answer using 3 and return.
(3) If M1/2 is an integer, we can know that M=P2 or M=P2
Q2. No matter which situation, we can always update answer using 2 and return.
(4) If (1)(2)(3) are false, we can know that answer=1.
Since there are just O(N1/5/log(N)) prime numbers, so the expected running time is O(T*N1/5/log(N)).


让我们首先使用不大于N ^(1/ 5)的素数对N进行因式分解。
我们将M表示为分解后剩余的数,由于小于N ^(1/ 5)的素数都已经被分解了,剩下的M的所有因子都大于N ^(1/ 5)。
如果得到的M = 1那么接下来的工作都不用做了,结果就是1
否则M只能分解为:
P 1 P^1 P1,
P 2 , P ∗ Q P^2, P*Q P2,PQ
P 3 , P ∗ Q 2 P^3, P*Q^2 P3,PQ2
P 4 , P ∗ Q 3 , P 2 ∗ Q 2 P^4, P*Q^3, P^2*Q^2 P4,PQ3,P2Q2 的形式, 可以发现,除了第一列外,其余结果都是1

因此:
(1)如果M^(1 / 4)是整数,我们可以知道M = P^4。 使用4更新答案并直接返回更新后的答案。
(2)如果M^(1 / 3)是整数,我们可以知道M = P^3。 使用3更新答案并直接返回更新后的答案。
(3)如果M^(1 / 2)是整数,我们可以知道M = P^2。用2更新答案并直接返回更新后的答案。
(4)如果(1)(2)(3)为假,我们从上面情况的列举可以知道答案其余答案都为1。

AC Code(标程风格勉强可接受版):

先模仿一波市面上常见的 “题解”、“标程” 的代码。。。
用尽全身力气把代码全部挤在一坨,刻意把代码放的很短

#include<bits/stdc++.h>
using namespace std;
const int maxn = 4000;
bool notPrime[maxn];
int primes[maxn];
int t, cnt, ans = 0x3f3f3f3f;
long long n;
void init() {
    for(int i = 2; i < maxn; i++) if(!notPrime[i]) for(int j = i * i; j < maxn; j += i) notPrime[j] = true;
    for(int i = 2; i < maxn; i++) if(!notPrime[i]) primes[++primes[0]] = i;
}
bool test(long long n, long long k) {
    if(k ==  1) {ans = 1; return true;}
    long long foo = (long long)( pow(n, 1.0 / k) + 1e-6), res = 1;
    for(int i = 0; i < k; ++i) res *= foo;
    ans = (res == n && k < ans) ? k : ans;
    return res == n;
}
template<class T>
inline bool read(T &ret) {
    char c; int sgn;
    if(c = getchar(), c == EOF) return 0;
    while(c != '-' && (c < '0' || c > '9')) c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}
inline void out(int x) { if(x > 9) out(x / 10); putchar(x % 10 + '0');}
int main() {
    for(init(), read<int>(t); t--; ) {
        read<long long>(n);ans = 0x3f3f3f3f;
        for(int i = 1; i <= primes[0]; i++) {
            if(n % primes[i] == 0) {
                for(cnt = 0; n % primes[i] == 0;) {n /= primes[i]; cnt++;};
                ans = ans > cnt ? cnt : ans;
            }
            if(ans == 1 || n == 1) break;
        }
        if(ans != 1 && n > 1)
            for(int f = 4; f >= 1 && !test(n, f); --f);
        out(ans);putchar('\n');
    }
    return 0;
}

AC Code("标程"中级版):

#include<bits/stdc++.h>
using namespace std;const int maxn = 4000;bool notPrime[maxn];int primes[maxn];int t, cnt, ans = 0x3f3f3f3f;
long long n;void init() {for(int i = 2; i < maxn; i++) if(!notPrime[i]) 
for(int j = i * i; j < maxn; j += i) notPrime[j] = true;
for(int i = 2; i < maxn; i++) if(!notPrime[i]) primes[++primes[0]] = i;}
bool test(long long n, long long k) {if(k ==1) {ans = 1; return true;}long long foo = (long long)( pow(n, 1.0 / k) + 1e-6),
res = 1;for(int i = 0; i < k; ++i) res *= foo;ans = (res == n && k < ans) ? k : ans;return res == n;}
template<class T>inline bool read(T &ret) {char c; int  sgn;if(c = getchar(), c == EOF) return 0;while(c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');while(c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;return 1;}inline void out(int x) { if(x > 9) out(x / 10); putchar(x % 10 + '0');}
int main() {for(init(), read<int>(t); t--; ) {read<long long>(n);ans = 0x3f3f3f3f;for(int i = 1; i <= primes[0]; i++) {
if(n % primes[i] == 0) {for(cnt = 0; n % primes[i] == 0;) {n /= primes[i]; cnt++;};ans = ans > cnt ? cnt : ans;}
if(ans == 1 || n == 1) break;}if(ans != 1 && n > 1)for(int f = 4; f >= 1 && !test(n, f); --f);out(ans);putchar('\n');}
return 0;}

AC Code("标程"魔鬼版):

#include<bits/stdc++.h>
using namespace std;typedef long long LL;const int maxn=4000;bool notPrime[maxn];int primes[maxn];int t,cnt,ans=0x3f3f3f3f;LL n;void init(){for(int i=2;i<maxn;i++)if(!notPrime[i])for(int j=i*i;j<maxn;j+=i)notPrime[j]=true;for(int i=2;i<maxn;i++)if(!notPrime[i])primes[++primes[0]]=i;}bool test(LL n,LL k){if(k==1){ans=1;return true;}LL foo=(LL)(pow(n,1.0/k)+1e-6),res=1;for(int i=0;i<k;++i)res*=foo;ans=(res==n&&k<ans)?k:ans;return res==n;}template<class T>inline bool read(T&ret){char c;int sgn;if(c=getchar(),c==EOF)return 0;while(c!='-'&&(c<'0'||c>'9'))c=getchar();sgn=(c=='-')?-1:1;ret=(c=='-')?0:(c-'0');while(c=getchar(),c>='0'&&c<='9')ret=ret*10+(c-'0');ret*=sgn;return 1;}inline void out(int x){if(x>9)out(x/10);putchar(x%10+'0');}int main(){for(init(),read<int>(t);t--;){read<LL>(n);ans=0x3f3f3f3f;for(int i=1;i<=primes[0];i++){if(n%primes[i]==0){for(cnt=0;n%primes[i]==0;){n/=primes[i];cnt++;};ans=ans>cnt?cnt:ans;}if(ans==1||n==1)break;}if(ans!=1&&n>1)for(int f=4;f>=1&&!test(n,f);--f);out(ans);putchar('\n');}return 0;}

AC Code 正经版:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 4000;
int notPrime[maxn], primes[maxn];
void init() {
    int foo = sqrt(maxn);
    for(int i = 2; i < foo; i++)
        if(!notPrime[i])
            for(int j = i * i; j < maxn; j += i)
                notPrime[j] = 1;
    for(int i = 2; i < maxn; i++)
        if(!notPrime[i])
            primes[++primes[0]] = i;
}
template<class T>
inline bool read(T &ret) {
    char c;
    int sgn;
    if(c = getchar(), c == EOF)
        return 0; //EOF
    while(c != '-' && (c < '0' || c > '9'))
        c = getchar();
    sgn = (c == '-') ? -1 : 1;
    ret = (c == '-') ? 0 : (c - '0');
    while(c = getchar(), c >= '0' && c <= '9')
        ret = ret * 10 + (c - '0');
    ret *= sgn;
    return 1;
}

bool test(long long n, long long k) {
    if(k == 1)
        return true;
    long long foo = (long long)( pow(n, 1.0 / k) + 1e-6);
    long long res = 1;
    for(int i = 0; i < k; ++i)
        res *= foo;
    return res == n;
}
inline void out(int x) {
    if(x > 9)
        out(x / 10);
    putchar(x % 10 + '0');
}
int main() {
    int t;
    init();
    read<int>(t);
    while(t--) {
        long long n;
        read<long long>(n);
        int ans = 0x3f3f3f3f;
        for(int i = 1; i <= primes[0]; i++) {
            if(n % primes[i] == 0) {
                int cnt = 0;
                while(n % primes[i] == 0) {
                    n /= primes[i];
                    cnt++;
                }
                ans = ans > cnt ? cnt : ans;
            }
            if(ans == 1 || n == 1) break;
        }
        if(ans != 1 && n > 1) {
            for(int f = 4; f >= 1; --f)
                if(test(n, f)) {
                    ans = min(ans, f);
                    break;
                }
        }
        out(ans);
        putchar('\n');
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值