ecnu 故事 数学

由于你瞬间解决了小强多年以来的烦恼,小强十分高兴,于是他给大家讲了一个故事:“ 传说从前有个叫舍罕的印度国王,因为他的宰相发明了国际象棋,打算予以奖赏一番。国王问宰相想要什么,宰相对国王说:‘ 陛下,请您在这个棋盘的第一个格子里赏给我 1 粒麦子,在第二个格子里给 2 粒,第三个给 4 粒,以后每一个格子都比前一个多 1 倍,请您将这个棋盘上的 64 个格子全部摆满。’ 国王没宰相会算账,所以当即一口答应,殊不知若要满足宰相的这个看似简单的要求,全世界两千年也生产不出这么多麦子。这就是数学上著名的 ‘ 麦粒问题 ’。实际上最后颗数就是 2^0+2^1+2^2+…+2^63=2^64-1。由此可见一个小小的 2 有多大的威力!嘿嘿。” 小强笑得很诡异,大家都知道一场头脑的风暴又要来了 ……“ 下面我们来玩一个抢答游戏,我每次给大家一个非负整数 n,大家抢答一个整数 p,这个 p 满足关于 x 的方程 p^x=n 有整数解,由于 p 可能有多个,最小的就是正确答案!”

Input

输入一个整数 n (0<=n<=2^30),找出最小的整数 p,使 n=p^k,这里 k 也是整数。n 为-1 表示输入结束,并且该情况不作处理。

Output

对于每个输入,输出 p,如果不能找到最小解输出 "no answer"(不输出引号)。


解法:

枚举k,k为0到30之间的某个数。已知k和n就能求出p大致范围,用pow(n,1.0/k)近似,然后枚举p就能知道符合题目意思的p是否存在。

本来这是很简单的题目,但是有几个trap要注意,k为偶数,p最小为负数且p的绝对值在其取值范围内最大。

第二个是,n=1时,任意数除了零本身的零次方都为1,所以p可取无穷小的负数,所以输出no answer

代码:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

ll cal(ll x,ll y){
    ll ans=1;
    for(int i=0;i<y;i++){
        ans*=x;
    }
    return ans;
}

int main()
{
    ll n;
    while(scanf("%lld",&n)){
       if(n==-1)break;
       if(n==0){printf("0\n");continue;}
       if(n==1){printf("no answer\n");continue;}
       ll k=32;
       ll ans=1e17;
       int flag=0;
       for(k=31;k>1;k-=2){
            ll p= max(1LL,(ll)(pow(n,1.0/k))-5);
            for(;;p++){
                ll x=cal(p,k);
                if(x>n)break;
                if(x==n){
                    ans=min(ans,p);
                    flag=1;
                    break;
                }
            }
            if(flag)break;
       }
       int flag1=0;
       for(k=2;k<=32;k+=2){
            ll p= (ll)(pow(n,1.0/k))+5;
            for(;;p--){
                ll x=cal(p,k);
                if(x<n)break;
                if(x==n){
                    ans=min(ans,-p);
                    flag1=1;
                    break;
                }
            }
            if(flag1)break;
       }
       if(flag+flag1==0)printf("%lld\n",n);
       else printf("%lld\n",ans);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值