CSP历年复赛题-P1010 [NOIP1998 普及组] 幂次方

原题链接:https://www.luogu.com.cn/problem/P1010

题意解读:输出一个正整数的 的幂次方表示,需要用到二进制数学知识,将整数拆解成2的次幂之和,幂次方也要进行拆解,因此容易想到通过递归处理。

解题思路:

先看样例,给定整数137,要拆解成2的幂次方之和,

先考虑i使得刚好137>=2^i时,i取7,因此2^7是一个因子,137-2^7 = 137 - 128 = 9

再考虑i使得刚好9>=2^i时,i取3,因此2^3是一个因子,9 - 2^3 = 9 - 8 = 1

最后考虑i使得刚好1>=2^i时,i取0,因此2^0是一个因子,1 - 2^0 = 1 - 1 = 0

这样就完成了拆解137 = 2^7 + 2^3 + 2^0

因为整数最大是20000,因此每次在遍历找到第一个i时,可以从i=15开始递减,因为2^15 = 32768 > 20000 > 2^14 = 16384

要按格式输出结果,就需要递归处理

具体递归过程请参考代码注释。

100分代码:

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

int n;
int pow2[20]; //预计算2^i,pow2[i]表示2^i

//预计算pow2[20]
void init()
{
    int num = 1;
    pow2[0] = num;
    for(int i = 1; i <= 20; i++)
    {
        num *= 2;
        pow2[i] = num;
    }
}

//递归处理
void decode(int x)
{
    if(x == 0) //是0的时候就不需要拆解成2的次方了,直接输出
    {
        cout << "0";
        return;
    }

    for(int i = 15; i >=0; i--) //由于最大值是20000,要将x拆解多个2的次方之和,从2^15开始看是否够减,依次往后看
    {
        if(x >= pow2[i])
        {
            cout << "2";
            if(i != 1) //如果2^1,则直接输出2即可,不需要(1)
            {
                cout << "(";
                decode(i);
                cout << ")"; 
            }  

            x -= pow2[i];
            break; //只需要找第一个满足要求的i,剩下的交给递归处理
        } 
    }

    if(x > 0) //如果x减去2^i之后不为0,继续递归处理剩下的部分
    {
        cout << "+"; //+加上剩下的部分
        decode(x);
    }
}

int main()
{
    init(); //先预计算出2^i,存入pow2[20],便于后面使用
    cin >> n;
    decode(n);
    return 0;
}

 

posted @ 2024-05-20 09:23  五月江城  阅读(66)  评论(0编辑  收藏  举报