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;
}

浙公网安备 33010602011771号