杂题杂记 2025.7.4始

葬送的杂题

这里是人类智慧闪耀时,某些东西毫无章法,故不陈述来历。

0.1 [ABC150F] Xor Shift

给定两个长度为 \(n\) 的序列 \(a=\{a_0,a_1,\cdots,a_{n-1}\}\)\(b=\{b_0,b_1,\cdots,b_{n-1}\}\),输出所有有序数对 \((k,x)\) ,满足:

  1. \(0\leq k<n\)\(x\geq 0\)
  2. 序列 \(a'=b\),其中 \(a'_i = a_{i+k\bmod n}\operatorname{xor} x\ (0\leq i<n)\),“\(\operatorname{xor}\)”表示按位异或。

注意到异或差分有这样一个性质 \(a_i \oplus b_i = (a_i \oplus k) \oplus (b_i \oplus k)\),所以对于序列 \(a,b\) 做一次差分,只需比较差分数组是否相同即可。

如何比较一段连续的数组是否相同?

可以用哈希,也可以用 \(\textbf{KMP}\)

\(a\) 的差分数组复制一份,这样可以处理循环节问题。

\(\huge \mathscr{Code}\)

#include<bits/stdc++.h>
using namespace std;
const int N = 4e5+100;
int n,m,a[N],b[N],da[N],db[N],nxt[N];
vector<int> ans;
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		a[i+n] = a[i];
	}
	for(int i=1;i<=n;i++) cin>>b[i];
	for(int i=1;i<2*n;i++){
		da[i] = a[i]^a[i+1];
		db[i] = b[i]^b[i+1];
	}
	da[2*n] = -1,db[n] = -2;
	int j = 0,k = 0;
	// Getnxt
	for(int i=2;i<n;i++){
		while(j && db[i]!=db[j+1]) j = nxt[j];
		if(db[j+1]==db[i]) j++;
		nxt[i] = j;
	}
	// KMP
	for(int i=1;i<2*n;i++){
		while(k && db[k+1]!=da[i]) k = nxt[k];
		if(db[k+1]==da[i]) k++;
		if(k==n-1){
			ans.push_back(i-k+1);
		}
	}
	for(int e:ans){
		if(e==n+1) continue;
		cout<<e-1<<' '<<(a[e]^b[1])<<'\n';
	}
	return 0;
}

posted @ 2025-08-04 18:56  OrangeRED  阅读(7)  评论(0)    收藏  举报