题解 P7071 【优秀的拆分(暂无数据)】
呵呵侠
2020-11-07 20:26:28
首先分析下题意,最重要的是这两句话:
```cpp
1.n被分解为了若干个不同的2的正整数次幂
……
2.注意,6=2+2+2 不是一个优秀的拆分,因为拆分成的3个数不满足每个数互不相同
```
仔细看一下,先来分析一下第一个条件:
2的正整数次幂一定是正整数个2相乘,所以必有
$$2 ^ n \bmod 2 = 0$$
即能分解的数必然是偶数,所以遇到奇数直接切 $\text{-1}$ 就OK了。
再看第二个条件:
“优秀的拆分”必须要满足每个数互不相同,意思也就是我们要用的是 $\text{if}$ 条件判断而并非是 $\text{while}$ 的循环。
接下来就难了,要判断 $2^m < n$ 里面的 $m$ 最小是多少,但是我分析了一下数据, $1 \le n \le 1 \times 10^7$ , $\text{Soga}$ !果断打表!
```cpp
#include <bits/stdc++.h>
using namespace std;
int n;
long long pow2[24] = {0, 8388608, 4194304, 2097152, 1048576, 524288, 262144, 131072, 65536, 32768, 16384, 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2}; // 打表大法好
int main()
{
freopen("power.in", "r", stdin);
freopen("power.out", "w", stdout); // 洛谷交的时候可以不写,但是比赛的时候一定加上,不然没分!
cin >> n;
if(n % 2 == 1)
{
cout << -1 << endl; // 遇到奇数,直接切出
return 0;
}
for(int i = 1; i <= 23; i = i + 1)
if(n >= pow2[i])
{
n = n - pow2[i];
cout << pow2[i] << " "; // 这里其实可以用while是因为我已经把2的幂排好序了,但是还是建议使用if
}
return 0; // 一定要return 0!不然可能没有分!
}
```