1 条题解

  • 0
    @ 2026-8-23 21:39:38

    直接说结论和证明:

    结论 1:Ai2K1A_i\ge2^{K-1}

    证明 1:假设 Ai<2K1A_i<2^{K-1},那么 Ai×2<2KA_i\times2<2^K,而且对于 AiA_i 可以覆盖的答案 Ai×2A_i\times2 必定也可以覆盖,而且还可能多覆盖一些数。

    结论 2:想象建立一颗 01Trie 维护所有大于 2K12^{K-1} 的数。我们的题目相当于找出 nn 条从根的链覆盖尽可能多的节点,每次选择一条最优的链,总覆盖点数就是最大的。

    证明 2:简单贪心,显然。

    关于代码,我认为我的写法不错:

    #include <bits/stdc++.h>
    using namespace std;
    int log2_(int k) {
    	int l = 0, r = 62;
    	while (l < r) {
    		if ((1ll << (l + r + 1 >> 1)) > k)
    			r = (l + r + 1 >> 1) - 1;
    		else
    			l = (l + r + 1 >> 1);
    	}
    	return l;
    }
    int T, n, k, realk, realn, flag[10000005], cnt;
    signed main()
    {
    	cin >> T;
    	while (T--)
    	{
    		cin >> n >> k;
    		if ((1 << (k - 1)) <= n) {
    			for (int i = 0; i < (1 << (k - 1)); i++)
    				cout << (1 << (k - 1)) + i << " ";
    			for (int i = (1 << (k - 1)) + 1; i <= n; i++)
    				cout << "1 ";
    			cout << endl;
    			continue;
    		}
    		cnt = 0;
    		realk = min(k, log2_(n) + 2);
    		realn = (1 << (realk - 1));
    		for (int i = 0; i < realn; i++) flag[i] = 0;
    		for (int i = (1 << realk); i; i >>= 1) {
    			for (int j = i; j < realn; j += (i << 1)) {
    				if (cnt < n) {
    					cnt++;
    					flag[j] = cnt;
    					cout << ((j + realn) << (k - realk)) << " ";
    				}
    				else {
    				  break;
    				}
    			}
    		}
    		cout << endl;
    	}
    	return 0;
    }
    
    • 1

    信息

    ID
    1232
    时间
    2000ms
    内存
    1024MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者