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; }
标签:第二场,mat,sz,int,res,++,多校,牛客,now From: https://www.cnblogs.com/zhujio/p/17575945.html