一个人的巴黎


私信TA

用户名:uq_36478041918

访问量:14982

签 名:

等  级
排  名 105
经  验 8303
参赛次数 1
文章发表 70
年  龄 0
在职情况 学生
学  校 NTU
专  业 计算机科学与技术

  自我简介:

解题思路: 

    一般来说,一个正整数可以拆分成若干个正整数的和。例如,1 = 1,10 =  1 + 2 + 3 + 4 等。
    对于正整数 n 的一种特定拆分,我们称它为“优秀的”,当且仅当在这种拆 分下,n 被分解为了若干个不同的 2 的正整数次幂。注意,一个数 x 能被表 示成 2 的正整数次幂,当且仅当 x 能通过正整数个 2 相乘在一起得到。
    例如,10 = 8 + 2 = 23 + 21 是一个优秀的拆分。但是,7 = 4 + 2 + 1 =  22 + 21 + 20 就不是一个优秀的拆分,因为 1 不是 2 的正整数次幂。
    现在,给定正整数 n,你需要判断这个数的所有拆分中,是否存在优秀的 拆分。若存在,请你给出具体的拆分方案。
注意事项:

    需要从大到小输出 这个拆分中的每一个数
参考代码:

#include<iostream>

using namespace std;

#include<cmath>

int judge(int n)//判断是否为2的幂次方

{

    int x;

    while (n)

    {

        x = n % 2;//余数

        n = n / 2;//商

        if (x == 1) //若余数为1,则不是2的幂次方

            return 0;

        if (x == 0 && n == 1)//若余数为0 时且商为1时,是2的幂次方(可自己举例验证)

            return 1;

    } 

}


//judge判断还可以采用一种更高级的方法,只需一行代码,原理如下:

//把一个数n拆成二进制看待处理的,如果 n 是 2 的幂次方的话,那么 n 的二进制数的最高位是 1,后面的都是 0。如果我们把它减 1,则会导致最高位变成 0,其余全部变成 1。然后我们把 n 和 (n - 1)进行与操作,结果就会是 0。例如:16=1 0000,(1 0000 & 0 1111)=0。代码如下:

//int judge(int n)

//{    return (n&(n-1))==0;    }  n&(n-1)的值为1,表示n不是2的幂次方,1!=0,此时返回0;反之,n&(n-1)的值为0,表明n是2的幂次方,0==0,成立,此时返回1


int fact(int n)//从大到小输出2的幂次方

{

    int i = 1;

    if (judge(n))//n本身就是2的幂次方,则它是"优秀的"

    {

        cout << n << " ";

        return 0;

    }

    for (i = 1; pow(2, i) < n; i++);//此处循环没有循环内容,是为了找出小于n的最大2的幂次方

    int a = pow(2, i - 1);

    cout << a<<" ";

    if (judge(n - pow(2,i)))//判断剩下的是不是 2 的正整数次幂

    {

        cout << n - pow(2, i-1)<<" ";

        return 0;

    }

    else//不是的话,递归寻找,通俗讲就是每次都减去一个小于n的最大2的幂次方,在差里寻找下一个小于差的最大2的幂次方

        fact(n - a);

}


int main()

{

    int n;

    cin >> n;

    if (n % 2 == 1)//奇数一定不是"优秀的"

        cout << "-1" << endl;

    else

        fact(n);

    return 0;

}


 

0.0分

4 人评分

  评论区

优秀的judge()
2022-02-15 22:08:27
  • «
  • 1
  • »