poj 1730 Perfect Pth Powers

题目大概意思 给你一个令 x=b^p 求最大的p
例如 81=9^2=3^4p的值为 4
一看蒙啦,这怎么求啊,数据范围在2^32次方之内,纠结,这种题一定会有算法,


再看列出几个例子来
例如: x                           p
        9=3*3                       2
       36=2*2*3*3              2
      100=2*2*5*5             2
      81=3*3*3*3=9*9       4
看出端倪儿来了没我来解释一下 9 36 100 81 都可以分解成素数之积 儿这些素数


个数的最大公约数就是p的值
有没有激动啦,终于理清思路了,开始写,用横扫千军之势写出代买为啥还是wa 
气愤了,不写了,我明明没错啊,怎么就过不了呢。浏览一下大家的讨论,晕,该


测试数据中含有令人气愤的负数而负数是没有偶次根的
再改,将求出的素数的公约数,如果为负数,就除以2直到遇到奇数,再输出如果不


是负数直接输出;这下该对了吧,可惜天不从人愿,还是wa
这是为嘛捏,再随便溜达溜达,忽然发现一组数据-2147483648  2147483648


照常理来说结果应该等于31可惜我的程序输出的是无论怎样该都是1
检查一下,我发现一个问题
      ifn<0
        n=-1;
或者 n=fabs((double)n);
这两种代码 如果n=-2147483648或者 --2147483648的话是不执行的,也就是说n


算是-2147483648,执行绝对值运算以后还是-2147483648
我无语了,why
但是abs(prime[i])>sqrt(fabs((double)n)) 是可以执行的而且结果是对的,那就



这样用吧;改过以后果然ac
注意问题:
负数问题
最大数问题
3 k个数的公约数问题
代码:



#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define maxnum 50001
long pnum[maxnum];
long prime[maxnum];
long l,n;
void init()
{
 long i,j;
 memset(pnum,0,sizeof(pnum));
 for(i=2;i<maxnum;i++)
 {
 for(j=2;j*i<maxnum;j++)
 pnum[j*i]=1;
 }
 l=0;
 for(i=2;i<maxnum;i++)
 if(pnum[i]!=1)
 {
 prime[l]=i;
 l++;
 }
}
long gcd(long a,long b)
{
 return b==0? a:gcd(b,a%b);
}
long solve(long n)
{
 long i;
 long x=n;
 long len=0;
 n=fabs((double)n);
 memset(pnum,0,sizeof(pnum));
 for(i=0;i<l&&n!=1&&n!=-1;i++)
 {
 if(abs(prime[i])>sqrt(fabs((double)n)))
 break;
 if(n%prime[i]==0)
 {
 while(n%prime[i]==0)
 {
 n/=prime[i];
 pnum[len]++;
 }
 len++;
 }
 }
 if(fabs((double)n)!=1)
 {
 pnum[len]++;
 len++;
 }
 if(len==0)
 return 1;
 if(x<0)
 for(i=0;i<len;i++)
 while(pnum[i]%2==0)
 pnum[i]/=2;
 if(len<2)
 return pnum[0];
 long m=gcd(pnum[0],pnum[1]);
 for(i=2;i<len;i++)
 m=gcd(pnum[i],m);
 if(x<0)
 while(m%2==0)
 m/=2;
 return m;
}
int main()
{
 init();
 while(scanf("%ld",&n)!=EOF)
 {
 if(n==0) break;
 printf("%ld\n",solve(n));
 }
 return 0;
}









 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值