Power Calculus ——快速幂

先来看看题目大意:

给定一个正整数n,求经过多少次乘法或除法运算可以从x得到x^n?中间结果也是可以复用的。
例如,求x^31,x^2 = x × x, x^4 = x^2 × x^2, x^8 = x^4 × x^4, x^16 = x^8 × x^8, x^32 = x^16 × x^16, x^31 = x^32 ÷ x.
至少需要6次运算,才可以得出x^31。

一拿到这个题,可能有些同学的思路是这样的,先让x^n累加,加到大于目标n时反过来减,比如473的过程:2 4 8 16 32 64 128 256 512 480 472 473共12次,512后先减32再减8加1

但是最优解却是2 4 8 16 32 31 62 126 252 504 473 共11次 ,31*2=62,62*2=126,126*2=252,252*2=504,504-31=473

所以说,一开始我们的想法就错啦,这种惯性思维不行,不行,不行,重要的事情说三遍,(我当初也是这么做的)

所以只能老实一点,搜索,怎么搜索呢,来看上面的例子,每一步都可能加上或者减去前一个已经出现的数,,有没有想法,下面来看代码,注释都在代码里面
老样子啦!!

#include<cstdio>
#include<algorithm>
using namespace std;

const int maxans=13;//为什么是13呢,这个留给你思考,最多就到13层,
                    //如果多了的话就是你代码有问题了
int n,a[maxans+1];  //这个数组用来存放计算过程

bool dfs(int d,int maxd)
{
    if(a[d]==n) return true;    //答案来喽!!
    if(d==maxd) return false;   //剪枝

    int maxv=a[0];              
    for(int i=1;i<=d;i++)
        maxv=max(maxv,a[i]);   //maxv表示当前计算出最大的x的幂
    //printf("maxv: %d   ",maxv);
    if((maxv<<(maxd-d))<n) return false;  //如果让maxv继续乘
                                         //(maxd-d)次2,还小于n
                                         //的话,说明让它以最快的
                                         //速度增长都得不到结果
    //printf("maxv: %d\n",maxv);
    for(int i=d;i>=0;i--)
    {
        a[d+1]=a[d]+a[i];             //让d加上前面的第i个数
        if(dfs(d+1,maxd)) return true;
        a[d+1]=a[d]-a[i];             //让d减去前面的第i个数
        if(dfs(d+1,maxd)) return true;
    }
    return false;
}

int solve(int n)
{
    if(n==1) return 0;               //奇葩数据咱们单独处理
    a[0]=1;                          //初始化
    for(int maxd=1;maxd<maxans;maxd++)  //迭代加深
    {
        if(dfs(0,maxd))              //开始搜索
            return maxd;             //如果找到的话赶回当前层数
    }
    return maxans;                   //否则返回最大层数,再大也打不过它
}

int main()
{
    while(~scanf("%d",&n)&&n)
    {
        printf("%d\n",solve(n));
    }
    return 0;
}

算法呢就是一个多练,多想的过程,这道题说简单也简单,说难也难,想明白了就简单了,说实话,多多练习,,不努力永远不会,让AK不再是梦。

  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值