Skip to main content
Original242 words1 min

题解:P8942 Digital Fortress

Summary

多组询问,给定 n、m,问是否存在长度 n、元素都在 1 到 m 的单调不减正整数序列,使其前缀异或和与后缀异或和都单调不减,存在则给出一组。构造每个元素取二的幂 1、2、4、8……,前缀异或和为二的幂减一严格递增,后缀由对称性同样递增。要放进上界需最大元素二的 n-1 次方不超过 m;反过来前缀递增要求各元素最高位两两不同且递增,最大元素至少这么大,故该条件既必要又充分。时间复杂度 O(tlogm)。

题意简述​

多组询问。每次给定 n,mn,m,问是否存在长度为 nn、元素都在 [1,m][1,m] 的单调不减正整数序列,使其前缀异或和与后缀异或和都单调不减;存在则输出一组方案。

解题思路​

构造 ai=2i−1a_i=2^{i-1},即 1,2,4,8,…1,2,4,8,\dots。前缀异或和为 1,3,7,15,…1,3,7,15,\dots(即 2i−12^i-1)严格递增;由对称性,后缀异或和同样递增,恰好满足要求。

要把 an=2n−1a_n=2^{n-1} 放进 [1,m][1,m],需 2n−1≤m2^{n-1}\le m,即 n−1≤⌊log⁡2m⌋n-1\le\lfloor\log_2 m\rfloor。

反过来,前缀异或和递增要求每个 aia_i 都引入一个更高的最高位,故各元素的最高位两两不同且递增,最大元素至少为 2n−12^{n-1}。因此 2n−1≤m2^{n-1}\le m 既必要又充分:满足时输出 20,21,…,2n−12^0,2^1,\dots,2^{n-1},否则输出 No。

时间复杂度为 O(tlog⁡m)O(t\log m)。

参考代码​

341 Bcpp
#include <bits/stdc++.h>
using namespace std;

using ll=long long;
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin>>t;
while(t--)
{
int n;
ll m;
cin>>n>>m;
if(n<=63&&(1ll<<(n-1))<=m)
{
cout<<"Yes\n";
for(int i=0;i<n;i++)cout<<(1ll<<i)<<' ';
cout<<'\n';
}
else cout<<"No\n";
}
return 0;
}