杂题记 2

发布时间 2023-10-18 23:10:45作者: HaHeHyt

写在前面:题目难度高,大部分题个人认为的实际难度不低于洛谷的紫题。

\(\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;
}