题意:
给定 n, 求满足条件 x ^p = n 的最大的p的值;
思路:
还是考虑n的素因子,对n进行唯一分解以后(pi 为素因子, ni为个数) 得到 (p1 ^n1) * (p2 ^n2) * (p3 ^n3)...... = n;
要是n为正数的话,直接对 n1,n2,n3.....求 gcd 后就是 最大的p;
如果n为负数的话,要先对(-n)唯一分解,求得p,这个p必须得是 奇数,
如果p是偶数的话,相当于此时p 条件下的 x 中还有某个(或某些)素因子的个数是偶数,不合条件,需要一直 除以2,直到p为奇数;
扩展:唯一分解定理求因子个数。
代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
const int MAXN=1000100;
bool vis[MAXN];
long long prime[MAXN/10];
int tot=0;
void getPrime()//求素数
{
for(long long i=2;i<MAXN;i++)
if(!vis[i])
{
prime[tot++]=i;
for(long long j=i*i;j<MAXN;j+=i) vis[j]=true;
}
}
int a[1000];//保存素因子
int b[1000];//保存素因子的个数
int cnt;
void sbreak(long long n){//进行素因子分解
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
cnt=0;
for(int i=0;prime[i]*prime[i]<=n;i++){
if(n%prime[i]==0){
a[cnt]=prime[i];
while(n%prime[i]==0){
b[cnt]++;
n/=prime[i];
}
cnt++;
}
}
if(n!=1){
a[cnt]=n;
b[cnt++]=1;
}
}
int gcd(int a,int b) //求最大公约数
{
return b?gcd(b,a%b):a;
}
int main(){
int T,ans,kase=0,flag;
long long n;
getPrime();
scanf("%d",&T);
while(T--){
flag=1;//标志,判断n是正数还是负数
scanf("%lld",&n);
if(n<0) n=-n,flag=0;
sbreak(n);
int t=b[0];
if(!flag){//如果n是奇数
if(t%2==0){
while(t%2==0) t/=2;
}
for(int i=0;i<cnt;i++){//将它的素因子的个数化为奇数
if(b[i]%2==0){
while(b[i]%2==0) b[i]/=2;
}
t=gcd(t,b[i]);
}
}
else for(int i=0;i<cnt;i++)
{
//cout<<b[i]<<endl;//b[i]就是所求的每个ni。
t=gcd(t,b[i]);
}
printf("Case %d: %d\n",++kase,t);
}
return 0;
}