CF2066C Bitwise Slides
Problem
题目描述
给定一个数组 \(a_1, a_2, \ldots, a_n\),以及三个初始值为零的变量 \(P, Q, R\)。
你需要按从 \(1\) 到 \(n\) 的顺序依次处理所有数字 \(a_1, a_2, \ldots, a_n\)。当处理当前元素 \(a_i\) 时,你必须从以下三个操作中任选一个执行:
- \(P := P \oplus a_i\)
- \(Q := Q \oplus a_i\)
- \(R := R \oplus a_i\)
其中 \(\oplus\) 表示按位异或操作。
执行操作时必须遵守核心规则:每次操作后,三个数 \(P, Q, R\) 必须满足其中至少存在两个数相等。
所有 \(n\) 个操作共有 \(3^n\) 种可能的执行方式。求其中不违反核心规则的方式数量。由于答案可能很大,请输出其对 \(10^9 + 7\) 取模的结果。
输入格式
每个测试包含多个测试用例。第一行输入测试用例数 \(t\)(\(1 \le t \le 10^4\))。随后为各测试用例的描述。
每个测试用例的第一行包含一个整数 \(n\)(\(1 \le n \le 2 \cdot 10^5\))——数组 \(a\) 的长度。
每个测试用例的第二行包含 \(n\) 个整数 \(a_1, a_2, \ldots, a_n\)(\(1 \le a_i \le 10^9\))——数组 \(a\) 的元素。
保证所有测试用例的 \(n\) 之和不超过 \(2 \cdot 10^5\)。
输出格式
对于每个测试用例,输出不违反核心规则的操作方式数量对 \(10^9 + 7\) 取模后的结果。
输入输出样例 #1
输入 #1
5
3
1 7 9
4
179 1 1 179
5
1 2 3 3 2
12
8 2 5 3 9 1 8 12 9 9 9 4
1
1000000000
输出 #1
3
9
39
123
3
说明/提示
第一个测试用例中,存在 3 种合法操作序列:PPP、QQQ、RRR。
第二个测试用例中,存在 9 种合法操作序列:PPPP、PPPQ、PPPR、QQQP、QQQQ、QQQR、RRRP、RRRQ、RRRR。
翻译由 DeepSeek R1 完成
Solution
已经到比较轻松的 DP 题。
设 \(dp_{i,x,y}\) 表示第 \(i\) 次操作后不同的数为 \(x\),两个相同的数为 \(y\) 的方案数。那么即有转移:
我们关注到,每次操作后,\(P\) \(Q\) \(R\) 三个数中一定有两个相等,所以三个数的异或和即为三个数中,与另外两个数不相等的那一个(如果三个数都相等即为任意一个),而三个数的异或和又等于前 \(i\) 个数的异或和,所以前 \(i\) 个数的异或和即为第 \(i\) 次操作后不同的那个数。所以每次操作后不同的那个数是一个定值,那么我们就可以将 dp 状态的第二维直接删去,再通过滚动数组将第一维删去,只留下最后一维。转移如下:
我们关注到虽然每次操作后,\(x\) 的值域范围为 \(0\le x\le 10^9\),但是最多只有 \(n\) 种,所以我们采用动态开店线段树来节省空间(当然也可以使用 map)。
Code
#include<bits/stdc++.h>
#define int long long
#define N 200005
#define mod 1000000007
using namespace std;
int T,n,mx;
int a[N];
struct s_tree{
int rt=0,idx=0;
struct node{int ls,rs,sum;}t[N<<2];
inline void add(int &id,int l,int r,int x,int val){
if(!id)id=++idx;
if(l==r){
t[id].sum=(t[id].sum+val)%mod;
return;
}
int mid=(l+r)>>1;
if(x<=mid)add(t[id].ls,l,mid,x,val);
else add(t[id].rs,mid+1,r,x,val);
t[id].sum=(t[t[id].ls].sum+t[t[id].rs].sum)%mod;
}
inline int query(int id,int l,int r,int x){
if(!id)return 0;
if(l==r)return t[id].sum;
int mid=(l+r)>>1;
if(x<=mid)return query(t[id].ls,l,mid,x);
else return query(t[id].rs,mid+1,r,x);
}
inline void clear(){
for(int i=1;i<=idx;i++)t[i].ls=t[i].rs=t[i].sum=0;
rt=idx=0;
}
}tr;
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>T;
while(T--){
tr.clear();
cin>>n;
mx=0;
for(int i=1;i<=n;i++)cin>>a[i],mx=max(mx,a[i]);
tr.add(tr.rt,0,(mx<<1),0,1);
int s=0;
for(int i=0;i<n;i++){
int val=tr.query(tr.rt,0,(mx<<1),(s^a[i+1]))+tr.query(tr.rt,0,(mx<<1),s);
tr.add(tr.rt,0,(mx<<1),s,2*val);
(s^=a[i+1]);
}
cout<<tr.t[tr.rt].sum<<"\n";
}
return 0;
}

浙公网安备 33010602011771号