杂题杂记 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)\) ,满足:
- \(0\leq k<n\) 且 \(x\geq 0\)。
- 序列 \(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;
}

浙公网安备 33010602011771号