题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1220
题目大意:
给你一个 x,请求出一个最大的 p 使得 np = x(n为任意整数)。注意,x 有可能是负数。
解题思路:
算术基本定理。
求出 |x| 的唯一分解式,然后求各项指数的最大公因数。如果 x<0,那么还要事先将分解式的每一项的指数都转化成奇数(负数的偶数次方就变成正数了嘛)。
AC代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 5 using namespace std; 6 typedef long long ll; 7 const int maxn = 1e5; 8 bool not_prime[maxn]; 9 int prime[maxn]; 10 int cnt; 11 void init(){ 12 cnt=0; 13 not_prime[0]=not_prime[1]=true; 14 for(ll i=2;i<maxn;i++){ 15 if(!not_prime[i]){ 16 prime[cnt++]=i; 17 for(ll j=i*i;j<maxn;j+=i) 18 not_prime[j]=true; 19 } 20 } 21 } 22 int gcd(int a,int b){ 23 if(b==0) return a; 24 return gcd(b,a%b); 25 } 26 int ind[maxn]; 27 int solve(ll x){ 28 bool fu=false; 29 if(x<0){ 30 fu=true; 31 x=-x; 32 } 33 int tmp=0; 34 for(int i=0;i<cnt;i++){ 35 if(x%prime[i]==0){ 36 ind[tmp]=1; x/=prime[i]; 37 while(x%prime[i]==0){ 38 ind[tmp]++; 39 x/=prime[i]; 40 } 41 tmp++; 42 } 43 } 44 if(x>1) ind[tmp++]=1; 45 if(fu){ 46 int ret=ind[0]; 47 while(ret%2==0) ret/=2; 48 if(ret==1) return 1; 49 for(int i=1;i<tmp;i++){ 50 while(ind[i]%2==0) ind[i]/=2; 51 ret=gcd(ret,ind[i]); 52 if(ret==1) return 1; 53 } 54 return ret; 55 } 56 else{ 57 int ret=ind[0]; 58 if(ret==1) return 1; 59 for(int i=1;i<tmp;i++){ 60 ret=gcd(ret,ind[i]); 61 if(ret==1)return 1; 62 } 63 return ret; 64 } 65 } 66 int main(){ 67 init(); 68 ll x; 69 int T; 70 scanf("%d",&T); 71 for(int t=1;t<=T;t++){ 72 scanf("%lld",&x); 73 printf("Case %d: %d ",t,solve(x)); 74 } 75 return 0; 76 }