写在前面:题目难度高,大部分题个人认为的实际难度不低于洛谷的紫题。
\(\color{lightblue}{\texttt{CF1848F. Vika and Wiki}}\)
\(\text{link}\) 。提示:考虑第 \(i\) 次会变成啥。
$\texttt{solution}$
下边设 \(a_k\) 为实际中的 \(a_{k\bmod n}\)。首先根据样例猜测一定有解。
按照提示,注意到第 \(1\) 次 \(a_i\gets a_i\ \text{xor}\ a_{i+1}\),第二次 \(a_i\gets a_i\ \text{xor}\ a_{i+1}\ \text{xor}\ a_{i+1}\ \text{xor}\ a_{i+2}=a_i\ \text{xor}\ a_{i+2}\)。
但是第三次似乎没啥规律?这时注意到可以倍增,第 \(2^k\) 次 \(a_i\gets a_i\ \text{xor}\ a_{i+2^k}\)。于是 \(k=\log_2n\) 一定是一个解。但是要求最小解。
由于我们可以快速求每 \(2^k\) 次操作数组会变成啥,直接倍增即可,类似倍增 \(\text{lca}\) 求出最大的不变为全 \(0\) 的操作数,最后 \(+1\) 即可。
$\texttt{code}$
#include<bits/stdc++.h>
#define LL long long
#define fr(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
using namespace std;
const int N=1<<20|5;
int n,a[N],b[N],ans;
int main()
{
ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
if(!*max_element(a,a+n)) return cout<<0,0;
for(int i=n/2;i;i>>=1)
{
for(int j=0;j<n;j++) b[j]=a[j];
for(int j=0;j<n;j++) b[j]^=a[(j+i)&(n-1)];
if(*max_element(b,b+n)){ans+=i;for(int j=0;j<n;j++) a[j]=b[j];}
}
return cout<<ans+1,0;
}