原题链接:传送门
题意:输入 t 组数n,每个数n = bp,求 p 的最大值。
思路:一开始以为是求 n = b1p1 * b2p2 * b3p3 * … *bnpn 中的最大的p,后来才注意到是 n = bp 中 p 的最大值…
可以先用唯一分解定理求出b1,b2,b3…bn,然后求出b1到bn的gcd,就是n = bp了。举两个例子12 = 22 * 3,gcd(2,1) = 1,那么12 = 121;144 = 24 * 3 2,gcd(4,2) = 2,那么144 = 122。
而且这道题还有个坑点,n为负数时,p必定为奇数(p为偶数时,不论b的正负,n一定是个正数),所以n是负数且p为偶数时,p要一直除2,直到p为奇数。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5+1;
int book[N],prime[N];
int cnt = 0;
void GetPrime(){ //素数打表
memset(book,0,sizeof(book));
for(int i=2;i<N;i++){
if(!book[i])
prime[cnt++] = i;
for(int j=0;j<cnt;j++){
if(i * prime[j] > N)
break;
book[i*prime[j]] = 1;
if(i % prime[j] == 0)
break;
}
}
}
int main(){
int t,Case = 1;
int sum,ans;
ll n;
scanf("%d",&t);
GetPrime();
while(t--){
scanf("%lld",&n);
ans = 0;
int flag = 0;
if(n < 0){ //n为负数时
n = -n;
flag = 1;
}
for(int i = 0;i<cnt && prime[i]*prime[i] <= n;i++){
sum = 0;
while(n % prime[i] == 0){ //唯一分解定理
n /= prime[i];
sum ++;
}
if(ans == 0)
ans = sum;
else ans = __gcd(ans,sum);
}
if(n != 1)
ans = 1;
if(flag){ //n为负数时
if(ans % 2 == 0) //ans必须是奇数
while(ans % 2 == 0)
ans /= 2;
}
printf("Case %d: %d\n",Case++,ans);
}
return 0;
}