P16834 【MX-X29-T5】『FeOI-6』Nako 和众数最小(简单版) 题解

· · 题解

:::::info[闲话] 没有人类了。 ::::: :::::success[Hint 1] 考虑答案下界,通过打表等方式猜测不同 n 时的答案大小。 ::::: :::::success[Hint 2] 考虑 n 是偶数的情况,通过打表同样可以得到构造方案。 ::::: :::::success[Hint 3] 考虑 n 是奇数的情况,考虑倒序字典序最大的序列,当出现格格不入的情况时大胆忽略。 ::::: :::::success[Hint 4] 考虑 n\equiv 7\pmod 8,继续考虑倒序字典序最大的序列。 :::::

对应 Hint 1:

我们观察答案下界,由于一共有 \frac{n(n+1)}{2} 个区间,容易发现答案下界为 \lceil\frac{n(n+1)}{4}\rceil

我们考虑通过使用 \Theta(2^n\text{poly}(n)) 的做法打表观察不同较小 n 的的具体答案,我们通过打表发现当 n\le 24 时只有 n=7 答案比 \lceil\frac{n(n+1)}{4}\rceil 大一,其它 n 答案都等于这个值,我们大胆猜测其余的 n 的答案都可以取到这个值,下文我们将通过构造证明这一点。

对应 Hint 2:

我们注意到部分分中对 n\bmod 8 进行了详尽的分讨,我们不妨对 n\bmod 8 分别考虑,同时我们注意到部分分中有一档全是偶数的部分分,我们考虑 n 是偶数的情况。

我们不妨再次打表观察,我们发现 n=2 时的唯二解是 [0,1][1,0]n=4 时的唯一解是 [0,1,1,0]n=6 时唯三解中存在两解分别为 [0,1,0,1,1,0][0,1,1,0,1,0],我们猜测对于任意 n 是偶数存在形式为 \lfloor\frac n4\rfloor[0,1]\lceil\frac n4\rceil[1,0] 拼接而形成的解,具体验证只需要暴力计算一下即可。

更加具体地,我们将 0 视为 -11 视为 +1,要求区间和非正,也就是问前缀和有多少非严格的逆序对。由于我们的前缀和形如 -1,0,-1,0,\cdots,-1,0,1,0,1,0,\cdots,1,0 那么逆序对数量我们是比较好算的。

更加具体地:

加和后容易证明构造是正确的。

对应 Hint 3:

我们考虑继续打表观察,我们发现 n=3 时唯一解是 [1,0,1]n=5 的两个解一个是 [0,1,0,1,1] 一个是 [1,1,0,1,0]n=7 时的最优解就比较多了,但是我们暴力枚举出的最优解中倒序字典序最大(正序也一样,反正如果你的暴力是写得比较正常那么大概率就是第一个或者最后一个)的解为 [0,0,1,0,1,1,1]n=9 的这个是 [0,0,0,1,0,0,1,1,1,1,1],看上去非常有规律,我们可以总结一下递推规律:

根据上面的递推规律,我们可以得出更加一般的规律(令 p=\lfloor\frac n8\rfloor):

但是我们经过计算后发现 $8p+7$ 时没有恰好取到下界,也就是说无法解决 $n=15,23\cdots$ 的情况,我们下面继续讨论。 #### 对应 Hint 4: 我们不妨依旧考虑倒序字典序最大的序列,我们发现 $n=15$ 时序列是 $[1,0,0,1,0,0,0,0,1,1,1,1,1,1,1]$,$n=23$ 时序列是 $[1,0,0,0,0,0,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1]$,看上去也比较有规律,我们容易得到序列是由 $1$ 个 $1$、$3p-1$ 个 $0$、$1$ 个 $1$、$p+3$ 个 $0$、$4p+3$ 个 $1$ 组成的,验证环节略去。 这样我们就做完了这道题。 时间复杂度为 $\Theta(n)$,空间复杂度为 $\Theta(1)$。 :::::success[code] ```cpp #include<bits/stdc++.h> #define inl inline #define int long long #define lll __int128 #define fst ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define rep(i,x,y) for(int i=x;i<=(y);++i) #define per(i,x,y) for(int i=x;i>=(y);--i) #define rpr(i,x,y,z) for(int i=x;i<=(y);i+=z) #define epe(i,x,y,z) for(int i=x;i>=(y);i-=z) #define repe(i,x,y) for(i=x;i<=(y);++i) #define endl '\n' #define INF 1e16 #define pb push_back #define pob pop_back #define pf push_front #define pof pop_front #define fi first #define se second #define lcm(x,y) x/__gcd(x,y)*y #define ull unsigned long long #define prr make_pair #define pii pair<int,int> #define gt(s) getline(cin,s) #define at(x,y) for(const auto &x:y) #define ff fflush(stdout) #define mt(x,y) memset(x,y,sizeof(x)) #define idg isdigit #define fp(s) string ssss=s;freopen((ssss+".in").c_str(),"r",stdin);freopen((ssss+\ ".out").c_str(),"w",stdout); #define sstr stringstream #define all(x) x.begin(),x.end() #define mcy(a,b) memcpy(a,b,sizeof(b)) #define ui unsigned #define si signed #define eb emplace_back #define pff(x) ((x)*(x)) #define eush emplace #define double long double #define pdi pair<double,int> #ifdef __unix__ #define gc getchar_unlocked #else #define gc _getchar_nolock #endif #ifdef __unix__ #define pc putchar_unlocked #else #define pc _putchar_nolock #endif using namespace std; inl void solve(){ int n; cin>>n; if(!(n&1)){ cout<<(n*(n+1)+3>>2)<<endl; rep(i,1,n>>1) if(i<=n>>2) cout<<0<<' '<<1<<' '; else cout<<1<<' '<<0<<' '; cout<<endl; return; } if(n==1){ cout<<1<<endl<<1<<endl; return; } if(n==7){ cout<<15<<endl<<1<<' '<<1<<' '<<0<<' '<<0<<' '<<1<<' '<<1<<' '<<0<<endl; return; } if((n&7)==1){ int p=n>>3; cout<<(n*(n+1)+3>>2)<<endl; rep(i,1,p*3-1) cout<<0<<' '; cout<<1<<' '; rep(i,1,p+1) cout<<0<<' '; rep(i,1,p<<2) cout<<1<<' '; cout<<endl; return; } if((n&7)==3){ int p=n>>3; cout<<(n*(n+1)+3>>2)<<endl; rep(i,1,p*3) cout<<0<<' '; cout<<1<<' '; rep(i,1,p+1) cout<<0<<' '; rep(i,1,p<<2|1) cout<<1<<' '; cout<<endl; return; } if((n&7)==5){ int p=n>>3; cout<<(n*(n+1)+3>>2)<<endl; rep(i,1,p*3+1) cout<<0<<' '; cout<<1<<' '; rep(i,1,p+1) cout<<0<<' '; rep(i,1,p<<2|2) cout<<1<<' '; cout<<endl; return; } int p=n>>3; cout<<(n*(n+1)+3>>2)<<endl<<1<<' '; rep(i,1,p*3-1) cout<<0<<' '; cout<<1<<' '; rep(i,1,p+3) cout<<0<<' '; rep(i,1,p<<2|3) cout<<1<<' '; cout<<endl; } signed main(){ fst; int t; cin>>t; while(t--) solve(); return 'T'^'0'^'m'^'l'^'e'; } ``` :::::