题解 P7071 【优秀的拆分(暂无数据)】

呵呵侠

2020-11-07 20:26:28

Solution

首先分析下题意,最重要的是这两句话: ```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!不然可能没有分! } ```