I. Powers Of Two
Posted studyshare777
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了I. Powers Of Two相关的知识,希望对你有一定的参考价值。
A positive integer xx is called a power of two if it can be represented as x=2yx=2y, where y is a non-negative integer. So, the powers of two are 1,2,4,8,16,…1,2,4,8,16,….
You are given two positive integers n and kk. Your task is to represent n as the sum of exactly kk powers of two.
Input
Output
If it is impossible to represent n as the sum of kk powers of two, print NO.
Otherwise, print YES, and then print kk positive integers b1,b2,…,bk, such that each of bi is a power of two, and ∑i=1kbi=n∑i=1kbi=n. If there are multiple answers, you may print any of them.
Examples
input
9 4
output
YES
1 2 2 4
input
8 1
output
YES
8
input
5 1
output
NO
input
3 7
output
NO
题目分析:
给出一个数n,问能不能把它拆成k个由2的一次或多次方组成的和。
输出能不能并且输出一种拆法。
分析:
很自然地想到先把n写成2进制,二进制位上每个1的位置对应一个数。
如果二进制上有m个1,答案至少有m个。又因为n可以拆成n个1,所以只要m<=k<=n,就可以拆成k个。
关键是拆,因为每个2的次方数可以拆成2个(每个是它本身除以2),也就是说拆一次,总的数字数目就多一个,只要我们按最大的拆,就可以达到,我们要拆成多少个的结果。假设这个数为8,8可以不拆,个数为1(8)。8拆成2个,每个就是4(4,4),如果要3个,把4拆一下就可以。(4,2,2)。。。。。。最终8可以拆成8个1。也就是8可以拆的范围是1~8。
拆可以用bfs来拆,代码如下:
void depart(int x,int n) { queue<int> q; q.push(x); while(q.size()!=n) { int p=q.front(); q.pop(); q.push(p/2); q.push(p/2); } while(!q.empty()) { ll num=q.front(); printf("%lld ",num); q.pop(); } }
最后,要凑够k个数字,我们还要对其他的进行拆。因为每个数如果不拆的话,它是m,我们先把k-m。剩下的由每个数因为拆增加的个数凑出来。
先选定一个方向,比如从大到小拆。我们可以尽可能地把一个数多的拆。比如最后一个数是u,小于k,我们就可以把u全部拆成1。依次类推,当拆到一定程度,剩下的就输出它自己即可。
关于实现从大到小拆:我们可以先存到 栈stack(由小到大),依次取出大的,放进另一个 队列queue里面,再对队列里的依次拆。
注意要从大到小拆,因为后面大的数可能会超出评测要求。
代码:
#include<stdio.h> #include<algorithm> #include<iostream> #incl#include<stdio.h> #include<algorithm> #include<iostream> #include<cmath> #include<queue> #include<stack> #define MIN(x,y) x<y?x:y; using namespace std; typedef long long ll; void depart(int x,int n) { queue<int> q; q.push(x); while(q.size()!=n) { int p=q.front(); q.pop(); q.push(p/2); q.push(p/2); } while(!q.empty()) { ll num=q.front(); printf("%lld ",num); q.pop(); } } int main() { int n,k; scanf("%d%d",&n,&k); int u=0; int t=n; stack<int> qp; while(t) { if(t&1) { qp.push(u); } u++; t>>=1; } if(k>=qp.size()&&k<=n) { printf("YES "); if(k==1) { ll a=qp.top(); ll b=pow(2,a); printf("%lld ",b); } else if(k==qp.size()) { while(!qp.empty()) { ll num=qp.top(); ll mo=pow(2,num); printf("%lld ",mo); qp.pop(); } } else { k-=qp.size(); queue<int> pl; int tp=0; while(k>0&&!qp.empty()) { int kp=qp.top(); qp.pop(); ll p; if(kp==0) p=1; else p=pow(2,kp); k=k-p+1; pl.push(kp); } //能全拆的,拆成1 while(pl.size()>1) { int o=pl.front(); pl.pop(); int ko=pow(2,o); for(int i=0;i<ko;i++) { printf("1 "); } } //不能全拆的,按指定个数拆 int o=pl.front(); ll pp=pow(2,o)+k; depart(pp-k,pp); //输出剩下的 while(!qp.empty()) { int num=qp.top(); int mo=pow(2,num); printf("%d ",mo); qp.pop(); } putchar(‘ ‘); } } else printf("NO "); return 0; } ?
以上是关于I. Powers Of Two的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #486 (Div. 3) D. Points and Powers of Two
Codeforces 988D Points and Powers of Two 性质卡常
PE512Sums of totients of powers(欧拉函数)
Codeforces 622F The Sum of the k-th Powers
Educational Codeforces Round 7 F - The Sum of the k-th Powers 拉格朗日插值