洛谷P7071
一般来说,一个正整数可以拆分成若干个正整数的和。
例如,1 = 1 1=1 1 = 1 ,10 = 1 + 2 + 3 + 4 10=1+2+3+4 1 0 = 1 + 2 + 3 + 4 等。对于正整数 n n n 的一种特定拆分,我们称它为“优秀的”,当且仅当在这种拆分下,n n n 被分解为了若干个不同 的 2 2 2 的正整数 次幂。注意,一个数 x x x 能被表示成 2 2 2 的正整数次幂,当且仅当 x x x 能通过正整数个 2 2 2 相乘在一起得到。
例如,10 = 8 + 2 = 2 3 + 2 1 10=8+2=2^3+2^1 1 0 = 8 + 2 = 2 3 + 2 1 是一个优秀的拆分。但是,7 = 4 + 2 + 1 = 2 2 + 2 1 + 2 0 7=4+2+1=2^2+2^1+2^0 7 = 4 + 2 + 1 = 2 2 + 2 1 + 2 0 就不是一个优秀的拆分,因为 1 1 1 不是 2 2 2 的正整数次幂。
现在,给定正整数 n n n ,你需要判断这个数的所有拆分中,是否存在优秀的拆分。若存在,请你给出具体的拆分方案。
输入格式
输入只有一行,一个整数 n n n ,代表需要判断的数。
输出格式
如果这个数的所有拆分中,存在优秀的拆分。那么,你需要从大到小输出这个拆分中的每一个数,相邻两个数之间用一个空格隔开。可以证明,在规定了拆分数字的顺序后,该拆分方案是唯一的。
若不存在优秀的拆分,输出 -1。
输入输出样例 #1
输入 #1
输出 #1
输入输出样例 #2
输入 #2
输出 #2
说明/提示
样例 1 解释
6 = 4 + 2 = 2 2 + 2 1 6=4+2=2^2+2^1 6 = 4 + 2 = 2 2 + 2 1 是一个优秀的拆分。注意,6 = 2 + 2 + 2 6=2+2+2 6 = 2 + 2 + 2 不是一个优秀的拆分,因为拆分成的 3 3 3 个数不满足每个数互不相同。
数据规模与约定
对于 20 % 20\% 2 0 % 的数据,n ≤ 10 n \le 10 n ≤ 1 0 。
对于另外 20 % 20\% 2 0 % 的数据,保证 n n n 为奇数。
对于另外 20 % 20\% 2 0 % 的数据,保证 n n n 为 2 2 2 的正整数次幂。
对于 80 % 80\% 8 0 % 的数据,n ≤ 1024 n \le 1024 n ≤ 1 0 2 4 。
对于 100 % 100\% 1 0 0 % 的数据,1 ≤ n ≤ 10 7 1 \le n \le {10}^7 1 ≤ n ≤ 1 0 7 。
题解
很明显我们可以注意到,任意正整数表示为二进制后末位为0 (即其是偶数 ),则存在优秀的拆分。
当我们试图从二进制逆向回十进制时,我们对这个数的第n位乘以 2 n − 1 2^{n-1} 2 n − 1 ,并累加,由此我们可以得出:
Decimal = ∑ i = 0 n − 1 b i × 2 i \text{Decimal} = \sum_{i=0}^{n-1} b_i \times 2^i
Decimal = i = 0 ∑ n − 1 b i × 2 i
因此,当 b 0 = 0 b_0 = 0 b 0 = 0 时,又因为 b i ∈ { 0 , 1 } ∀ i b_i \in \{0, 1\} \quad \forall i b i ∈ { 0 , 1 } ∀ i ,所以此时该数一定存在优秀的拆分。
而且这个拆分就是这个公式去掉所有为0项的结果。
因此我们可以简单的通过位运算拆出来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <bits/stdc++.h> using namespace std;int main () { int n; cin >> n; if (n<=0 || n&1 ){ cout << -1 ; return 0 ; } int m, x; while (n&&(m=log2 (n))){ x = 1 << m; cout << x << " " ; n -= x; } return 0 ; }