专栏文章

手写的从前 题解

P11785题解参与者 12已保存评论 14

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
14 条
当前快照
1 份
快照标识符
@miqjnste
此快照首次捕获于
2025/12/04 05:53
3 个月前
此快照最后确认于
2025/12/04 05:53
3 个月前
查看原文

题意回顾

构造一个长度为 22 的非负整次幂的序列,这个序列中每个元素都要为 22 的非负整次幂,且序列的和为 mm
要求:最小化序列长度,在此基础上最小化序列字典序。
数据范围:1m10181 \le m \le 10^{18},数据组数不超过 10410^4 组。

分析

mm 二进制拆分,这是序列长度的下限,我们还需要补一些元素。
对于这个序列若想让字典序最小则需要从小到大排序,故我们考虑让最小的元素越小越好,每次将最小的一个元素如果是 11 那么跳过并记录,否则拆分为两个一半。如果元素个数足够直接输出结果即可(注意补上记录的 11)。

参考实现

CPP
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
int T;
long long m;
priority_queue<long long, vector<long long>, greater<long long> > pq;
bool check(long long x) {
	while(x % 2 == 0) x /= 2;
	return x == 1;
}
int main() {
	cin >> T;
	for(int ti = 1; ti <= T; ti++) {
		cin >> m;
		for(long long i = (1ll << 62); i >= 1; i >>= 1) {
			if(m >= i) m -= i, pq.push(i);
		}
		int ct1 = 0;
		while(!check(pq.size() + ct1)) {
			int num = pq.top();
			pq.pop();
			if(num == 1) ct1++;
			else {
				pq.push(num / 2);
				pq.push(num / 2);
			}
		}
		for(int i = 1; i <= ct1; i++) {
			printf("1 ");
		}
		while(!pq.empty()) {
			printf("%lld ", pq.top());
			pq.pop();
		}
		puts("");
	}
	return 0;
}

评论

14 条评论,欢迎与作者交流。

正在加载评论...