【算法篇】幂方分解

本来是在数据结构一书中看到了一种高效率求高次幂的算法,便想来这找找有没有类似的算法题,结果找到了这个题,让我思考了一整天。

int mi(int x, int n)
{
    if (n > 1)
    {
        if (n % 2 == 0)
            return mi(x, n / 2) * mi(x, n / 2);
        else
            return mi(x, (n - 1) / 2) * mi(x, (n - 1) / 2) * x;
    }
    else if (n == 1)
        return x;
    else if (n == 0)
        return 1;
    else
        return 0;
}

这是一个高效求x的n次方的值的函数,因为其不断对分,所以时间复杂度为O(logN),不用担心在求高次方时出现时间超限(其实尝试这个函数才是我做这个题的本意,没想到反而这里思考的时间最少)

接下来便是将数值中最大的2的n次方找出来

    for (i = 0; i < 100; i++)
        if (n < mi(2, i+1) && n>=mi(2, i))//查找最大的2的n次方
            a = i;//将指数保存

然后接下来要利用递归实现两大步:
1.将去除这最大的2的n次方后的数进行递归
2.若最大的2的n次方的这个n大于2,要对其进行递归

我思考的时间最多的便是这第2步,因为我对递归还不太熟练,走上了岔路,总想着将n递归后再变成字符串,再将其作为返回值返回到上一层函数,最终自然是花了很多时间,也没有想明白该怎么做。好在最后还是顿悟,既然是字符串,只要调整一下顺序,直接输出不就好了。

printf("2");
    if (a > 2)
    {
        printf("(");
        fen(a);//若指数大于2,将其递归
        printf(")");
    }
    else if(a!=1)//因为只能有2和0,所以指数为1时不能输出
        printf("(%d)", a);//输出括号和指数
    if (n - mi(2, a) != 0)//检查是否有剩余部分,有的话再输出一个加号,并将剩余部分递归
    {
        printf("+");
        fen(n - mi(2, a));
    }

最后放出来全部的代码:

#include<stdio.h>
int mi(int x, int n)
{
    if (n > 1)
    {
        if (n % 2 == 0)
            return mi(x, n / 2) * mi(x, n / 2);
        else
            return mi(x, (n - 1) / 2) * mi(x, (n - 1) / 2) * x;
    }
    else if (n == 1)
        return x;
    else if (n == 0)
        return 1;
    else
        return 0;
}
void fen(int n)
{
    int i = 0;
    int a;
    for (i = 0; i < 100; i++)
        if (n < mi(2, i+1) && n>=mi(2, i))
        {
            a = i;
        }
    printf("2");
    if (a > 2)
    {
        printf("(");
        fen(a);
        printf(")");
    }
    else if(a!=1)
        printf("(%d)", a);
    if (n - mi(2, a) != 0)
    {
        printf("+");
        fen(n - mi(2, a));
    }
}
int main()
{
    int n;
    scanf_s("%d", &n);
    fen(n);
    return 0;
}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值