codeforce 457DIV2 B题
题意:
题目给出两个整数n,k,(n<=10^18,k<=10^5),求一个含有k个整数的序列,要求以2为底,以序列内数字为幂的和为n,其中序列内最大的数最小,若有多个序列满足条件,输出字典序最大的一个。
样例:input :23 5 output:Yes 3 3 2 1 0 ,其中2^3+2^3+2^2+2^1+2^0=23=n
分析
两个点:1:2^n=2*2^n-1,也就是说答案序列中任何一个数x都可以变为两个x-1
2: 结合二进制化十进制的方法,可以得到用2的幂次方表示的n
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <iostream> 5 #include <map> 6 using namespace std; 7 long long n; 8 int k; 9 map<int,int>b; 10 int main(){ 11 cin>>n>>k; 12 int m=0; 13 while(n){ 14 b[m]=n&1; 15 n/=2; 16 if(b[m++])k--; 17 } 18 if(k<0){ 19 printf("No"); 20 return 0; 21 } 22 m--; 23 int i; 24 for(i=m;;i--){//使最大值最小 25 if(b[i]>k)break; 26 b[i-1]+=2*b[i]; 27 k-=b[i]; 28 b[i]=0; 29 } 30 int j; 31 for(j=min(0,i);j<=i;j++)if(b[j])break; 32 for(;;j--){ 33 if(!k)break; 34 if(b[j]){ 35 b[j]--; 36 b[j-1]+=2; 37 k--;} 38 } 39 printf("Yes\n"); 40 for(int ll=m;ll>=j;ll--) 41 for(int l=1;l<=b[ll];l++)printf("%d ",ll); 42 return 0; 43 }