牛客多校第二场-H
op1-->-x-1
op2-->x+1
由线性代数知识推每次操作要乘的矩阵,线段树维护一个矩阵信息
[op,d,1] 就是代表一个f(x)=kx+b的方程,根据线性代数知识用矩阵表示该方程 -> f(x)=op*x+d , 最后一个1只是凑矩阵用的 ,f代表该矩阵,因为刚开始就是x,所以op=1,d=0
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
const int sz=3;
const int N=2e5+5;
string s;
struct mat {
ll m[sz][sz];
mat() { memset(m, 0, sizeof m); }
mat operator-(const mat& T) const {
mat res;
for (int i = 0; i < sz; ++i)
for (int j = 0; j < sz; ++j) {
res.m[i][j] = (m[i][j] - T.m[i][j]);
}
return res;
}
mat operator+(const mat& T) const {
mat res;
for (int i = 0; i < sz; ++i)
for (int j = 0; j < sz; ++j) {
res.m[i][j] = (m[i][j] + T.m[i][j]);
}
return res;
}
mat operator*(const mat& T) const {
mat res;
int r;
for (int i = 0; i < sz; ++i)
for (int k = 0; k < sz; ++k) {
r = m[i][k];
for (int j = 0; j < sz; ++j)
res.m[i][j] += T.m[k][j] * r ;
}
return res;
}
mat operator^(ll x) const {
mat res, bas;
for (int i = 0; i < sz; ++i) res.m[i][i] = 1;
for (int i = 0; i < sz; ++i)
for (int j = 0; j < sz; ++j) bas.m[i][j] = m[i][j];
while (x) {
if (x & 1) res = res * bas;
bas = bas * bas;
x >>= 1;
}
return res;
}
}A,B,f,Tree[4*N],unit;
void build(int now,int l,int r){
if(l==r){
if(s[l-1]=='A')Tree[now]=A;
else Tree[now]=B;
return;
}
int mid=(l+r)>>1;
build(now*2,l,mid);
build(now*2+1,mid+1,r);
Tree[now]=Tree[now*2]*Tree[now*2+1];
}
mat qurey(int now,int l,int r,int x,int y){
if(x<=l&&y>=r)return Tree[now];
int mid=(l+r)>>1;
mat ans=unit;
if(x<=mid)ans=ans*qurey(now*2,l,mid,x,y);
if(y>mid)ans=ans*qurey(now*2+1,mid+1,r,x,y);
return ans;
}
int main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int n,q;cin>>n>>q>>s;
int last=0;
A.m[0][0]=A.m[1][1]=A.m[2][1]=-1;
A.m[2][2]=B.m[2][1]=1;
f.m[0][0]=f.m[0][2]=1;
for(int i=0;i<3;i++)B.m[i][i]=1,unit.m[i][i]=1;
build(1,1,n);
while(q--){
int l,r;cin>>l>>r;
string now;cin>>now;
int rl=(last^l)%n+1,rr=(last^r)%n+1;
l=min(rl,rr);r=max(rl,rr);
mat calc=f*qurey(1,1,n,l,r);
ll len=now.size(),t=0;
for(int i=0;i<len;i++)t=t*2+(now[i]-'0');
ll mod=1ll<<len;
last=((t*calc.m[0][0]%mod+mod)%mod+calc.m[0][1]%mod+mod)%mod;
for(int i=len-1;i>=0;i--){
if((last>>i)&1)cout<<1;
else cout<<0;
}
cout<<endl;
if(last<0)break;
}
return 0;
}