CSP-J 2020 T1 优秀的拆分(洛谷P7071

CSP-J 2020 T1 优秀的拆分

题目

一个很简单的带点数学的小模拟,利用贪心的思想,设\(2^i\le n\)且最大,\(i\)从大向小进行遍历,如果\(2^i \le n\)就让\(n-=2^i\)并输出\(2^i\),直到\(n=0\)或者\(i=1\)为止(\(i=1\)也要遍历到)。我们可以推出只要\(n\)是奇数就没有优秀的拆分,是偶数就有,见下方证明。

证明

这里因为是\(2\)的正整数次幂,所以我们可以用二进制的思想,因为二进制中的每一位正是\(2\)的正整数次幂(除第一位)。所有的十进制数都可以转为二进制数,但是当\(n\)为奇数时第一位为1,也就是\(n\)中有\(2^0\),即没有优秀的拆分。但当\(n\)为偶数时第一位为0而且因为所有的十进制数都可以转为二进制数,所以若\(n\)为偶数时肯定是有优秀的拆分的。

这里我们通过\(pow(2,\log_2 n)\)来求得\(\le n\)且最大的2的正整数次幂,\(\log_2 n\)\(2^i \le n\)且最大的\(i\)百度百科

代码

#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
int main()
{
	int n;
	cin>>n;
    if(n&1){
        //奇数没有优秀的拆分,直接输出-1即可
        cout<<"-1"<<endl;
        return 0;
    }
    //只要是偶数都可以拆分
	for(int i=(int)floor(log2(n));n&&i;i--){
        //求小于等于n且最大的
		int temp=pow(2,i);
		if(n>=temp){
			cout<<temp<<' ';
			n-=temp;
		}
	}
	return 0;
}
posted @ 2022-03-11 12:52  AC?别闹!  阅读(332)  评论(0)    收藏  举报