题解:P11326 【MX-S7-T4】「SMOI-R2」XA-Game
既然 A 的操作是变成两个数的异或和,那么我们不妨从整个序列的异或和入手,因为 A 的操作不会改变整个序列的异或和,而最后 A 获胜的充要条件是异或和为
于是我们来考虑 B 的操作对于异或和的影响。如果选择的两个数是
那么 B 的目标是让最终异或和为
为什么呢?我们先假设 B 每一步序列异或和都会改变,那如果 B 一直不选
所以 A 获胜的第一个条件就呼之欲出了:初始序列中至多有一个
消灭之后,B 的所有操作都会改变异或和,A 的所有操作都不改变异或和。问题就简单了,只需要保证
也就是 A 获胜的第二个条件:
于是可以开始 dp,记录三个东西:有没有出现过
考虑把这个第二维只有
实际上跑得很慢,但是注意到转移矩阵都是固定的,只是幂次不同。可以预处理光速幂优化,具体见代码。这样可以去掉一个
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int MOD=1000000007,B=1e5;
struct matrix{
int n,m,a[9][9];
matrix(int _n=0,int _m=0){n=_n,m=_m;memset(a,0,sizeof(a));}
void init(int op){
// 00ed / lastd / xorsum
n=m=8,memset(a,0,sizeof(a));
for(int i=0;i<8;i++)for(int d=0;d<=1;d++){
if(!(op&(1<<d))) continue;
if((i&4)&&!(i&2)&&!d) continue;
int ni=0;
ni|=(i&1^d),ni|=2*d;
if((i&4)||(!(i&2)&&d==0)) ni|=4;
a[i][ni]=op==3?1:2;
}
}
matrix operator*(const matrix &x)const{
matrix res(n,x.m);
for(int i=0;i<n;i++)for(int j=0;j<x.m;j++)for(int k=0;k<m;k++)
res.a[i][j]=(res.a[i][j]+a[i][k]*x.a[k][j])%MOD;
return res;
}
}pre[300010];
matrix mul(matrix a,int k){
if(!k) return a;
if(k%100000) a=a*pre[k%100000];
k/=100000;if(!k) return a;
if(k%100000) a=a*pre[B+k%100000];
k/=100000;if(!k) return a;
if(k%100000) a=a*pre[B+B+k%100000];
return a;
}
int T,n,m;
signed main(){
pre[1].init(3);
for(int i=2;i<=B;i++) pre[i]=pre[i-1]*pre[1];
pre[B+1]=pre[B];
for(int i=2;i<=B;i++) pre[i+B]=pre[i+B-1]*pre[B+1];
pre[B+B+1]=pre[B+B];
for(int i=2;i<=B;i++) pre[i+B+B]=pre[i+B+B-1]*pre[B+B+1];
cin>>T;
while(T--){
cin>>n>>m;
matrix res(1,8); res.a[0][2]=1;
int lst=0;
for(int i=1,x,v;i<=m;i++){
cin>>x>>v;
res=mul(res,x-lst-1);
matrix tmp; tmp.init(1<<v);
res=res*tmp;
lst=x;
}
res=mul(res,n-lst);
int tarxor=((n-1)/2)&1^1,ans=0;
for(int i=0;i<8;i++)if((i&1)==tarxor)
ans=(ans+res.a[0][i])%MOD;
cout<<ans<<endl;
}
return 0;
}