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=P2Q2. 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,P∗Q
P
3
,
P
∗
Q
2
P^3, P*Q^2
P3,P∗Q2
P
4
,
P
∗
Q
3
,
P
2
∗
Q
2
P^4, P*Q^3, P^2*Q^2
P4,P∗Q3,P2∗Q2 的形式, 可以发现,除了第一列外,其余结果都是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;
}