CF2667F - Bitwise Slides

题面

  • \(p_i=⊕_{j=1}^ia_j\),那么由题意,进行 i 次操作后,有 \(P⊕Q⊕R=p_i\)

  • 因为 P,Q,R 这三个数字必须不成对地不同,所以这三个数字中必有一个为 \(p_i\),因为另外两个相同的数异或为 0。

  • 考虑状态,对于 \(f_{i,x}\),其三元组状态包括 \((p_i,x,x),(x,p_i,x),(x,x,p_i)\)

  • 考虑转移:

对于 \(f_{i-1,x}\),可以转移到\(f_{i,x}\),因为 \(p_{i-1}⊕a_i=p_i\),可以操作等于 \(p_{i-1}\) 的那个值,共一个。
对于 \(f_{i-1,p_i}\) 可以 \(\times 2\) 转移到\(f_{i,p_{i-1}}\),因为 \(p_i⊕a_i=p_{i-1}\),可以操作等于 \(p_{i}\) 的那个值,共两个。
对于 \(f_{i-1,p_{i-1}}\) 可以 \(\times 3\) 转移到\(f_{i,p_{i-1}}\),因为 \(p_{i-1}⊕a_i=p_i\),可以操作等于 \(p_{i-1}\) 的那个值,共三个,此时不需要考虑第一种转移方案,这已经包含了那种情况。
  • 直接 dp 会爆空间,发现实际有用状态很小,实际只有 \(S∈{p_i}\),转移除了 \(f_{i,p_{i-1}}\) 都可以直接沿用上一次的状态,所以可以压维并离散化状态来减小空间。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll N=2e5+5,P=1e9+7;
ll n,a[N],p[N],c[N],d[N],f[N],ans;
void sol(){
	cin>>n,ans=0,f[0]=1;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		p[i]=(p[i-1]^a[i]);
		c[i]=p[i];
	}
	sort(c+1,c+n+1);
	ll m=unique(c+1,c+n+1)-c-1;
	for(int i=1;i<=n;i++){
		d[i]=lower_bound(c+0,c+m+1,p[i])-c;
	}
	for(int i=1;i<=n;i++){
		f[d[i-1]]=(3*f[d[i-1]]+2*f[d[i]])%P;
	}
	for(int i=0;i<=n;i++){
		(ans+=f[d[i]])%=P;
		f[d[i]]=0;
	}
	cout<<ans<<'\n';
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int T;
	cin>>T;
	while(T--)sol();
} 
posted @ 2025-02-16 22:18  xzhiflow  阅读(14)  评论(1)    收藏  举报