放假前大佬给出的9道训练题。这道题时间2s。刚开始想的就没去做。后来看这道题的时候,觉得这个题是一个锻炼思维的好题。
题意:让你把一个数n拆分成k个二的幂次之和,并且你要保证在最高位最大的情况下,字典序最大。
题解:先求出N的二进制,二进制的1所在的位即所求幂次,如果1的个数大于K,则肯定不行;如果小于K,则进行增加操作,可将一个2^n变成两个2^(n-1)。注意:由于要求n的最大值最小,且字典序最大,增加位的时候从最高位开始,整体降位,即将所有的n全部变成n-1。
举例 16 5
16 可以拆分为 4(10000)
(变换) 4 --->(3,3)---->(2,2,3)--->(2,2,2,2)--->(2,2,2,2,1) 此时满足条件 输出
代码:
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<bitset>
#include<math.h>
#include<string>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define pi acos(-1)
#define close ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
using namespace std;
typedef long long ll;
const int MAX_N=1000000+50;
const int INF=0x3f3f3f3f;
const double EPS = 1e-10;
ll mod = 1e9+7;
priority_queue<int>q,Q; //开两个优先队列的原因是 我们可以用来标记最高位
int s[MAX_N];
int main(){
ll n,k;
cin>>n>>k;
int cnt = 0;
while(n > 0){
ll b=1;
int a=0;
while(b*2<=n) b*=2,a++;
cnt++;
q.push(a);
Q.push(a);
n -= b;
}
if(cnt > k){
cout<<"No"<<endl;
return 0;
}
int temp = cnt;
while(temp<k){
int a = Q.top();
Q.pop();
a--;
Q.push(a);
Q.push(a);
temp++;
}
temp=Q.top();
while(cnt<k){
int a = q.top();
if(temp==a) break;
q.pop();
a--;
q.push(a);
q.push(a);
cnt++;
}
temp = 0;
while(q.size()){
s[temp++] = q.top();
q.pop();
}
while(cnt < k){
s[cnt - 1] = s[cnt - 1] - 1;
s[cnt] = s[cnt-1];
cnt++;
}
cout<<"Yes"<<endl;
for(int i = 0; i < cnt; i++){
if(i == 0) cout<<s[i];
else cout<<" "<<s[i];
}
cout<<endl;
return 0;
}
/*
********
************
####....#.
#..###.....##....
###.......###### ### ###
........... #...# #...#
##*####### #.#.# #.#.#
####*******###### #.#.# #.#.#
...#***.****.*###.... #...# #...#
....**********##..... ### ###
....**** *****....
#### ####
###### ######
##############################################################
#...#......#.##...#......#.##...#......#.##------------------#
###########################################------------------#
#..#....#....##..#....#....##..#....#....#####################
########################################## #----------#
#.....#......##.....#......##.....#......# #----------#
########################################## #----------#
#.#..#....#..##.#..#....#..##.#..#....#..# #----------#
########################################## ############
*/