- P193's solution
P193's Solution
- 2025-9-4 22:00:10 @
考虑构造矩阵并利用线段树维护操作,此时不难构造出对应矩阵:
$$X_i\begin{bmatrix}1 & 0 & 0 \\ v & 1 & 0 \\ 0 & 0 & 1\end{bmatrix} \xrightarrow{\text{Operation 1}}X_i' $$$$X_i\begin{bmatrix}1 & 0 & 0 \\ 0 & v & 0 \\ 0 & 0 & 1\end{bmatrix} \xrightarrow{\text{Operation 3}}X_i' $$$$X_i\begin{bmatrix}1 & 0 & 0 \\ 0 & 0 & 1 \\ 0 & 0 & 1\end{bmatrix} \xrightarrow{\text{Operation 4}}X_i' $$操作 2 只需对区间矩阵的和提取第一项即可,至此问题得到解决。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int P=1e9+7;
const int PTA=262144;
struct Square
{
int n,m;
int a[4][4];
};
Square operator+(Square a,Square b)
{
int n=a.n,m=b.m;
Square c=(Square){n,m,{{}}};
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
c.a[i][j]=a.a[i][j]+b.a[i][j];
if(c.a[i][j]>=P) c.a[i][j]-=P;
}
return c;
}
Square operator*(Square a,Square b)
{
if(a.m!=b.n) exit(-1);
int n=a.n,m=a.m,k=b.m;
Square c=(Square){n,k,{{}}};
for(int i=1;i<=n;i++)
for(int j=1;j<=k;j++)
c.a[i][j]=0;
for(int l=1;l<=m;l++)
for(int j=1;j<=k;j++)
for(int i=1;i<=n;i++)
{
c.a[i][j]+=a.a[i][l]*b.a[l][j]%P;
if(c.a[i][j]>=P) c.a[i][j]-=P;
}
return c;
}
const Square S1=(Square){1,3,{{},{0,0,1,1}}};
const Square S3=(Square){3,3,{{},{0,1},{0,0,1},{0,0,0,1}}};
inline Square SQ(int type,int conf)
{
switch(type)
{
case 1: return (Square){3,3,{{},{0,1},{0,conf,1},{0,0,0,1}}};
case 3: return (Square){3,3,{{},{0,1},{0,0,conf},{0,0,0,1}}};
case 4: return (Square){3,3,{{},{0,1},{},{0,0,1,1}}};
}
}
Square aa[530012],all[530012];
int ll[530012],rr[530012];
void init()
{
for(int i=1;i<=2*PTA-1;i++)
aa[i]=S3;
for(int i=1,j=PTA;i<=PTA;i++,j++)
{
all[j]=S1;
ll[j]=rr[j]=i;
}
for(int i=PTA-1;i>=1;i--)
{
all[i]=all[i+i]+all[i+i+1];
ll[i]=ll[i+i];
rr[i]=rr[i+i+1];
}
}
void add(int type,int conf,int l,int r,int b)
{
if(ll[b]==l&&rr[b]==r)
{
Square c=SQ(type,conf);
all[b]=all[b]*c;
aa[b]=aa[b]*c;
return;
}
Square d=aa[b];
aa[b]=S3;
aa[b+b]=aa[b+b]*d;
all[b+b]=all[b+b]*d;
aa[b+b+1]=aa[b+b+1]*d;
all[b+b+1]=all[b+b+1]*d;
if(l<=rr[b+b]) add(type,conf,l,min(r,rr[b+b]),b+b);
if(r>=ll[b+b+1]) add(type,conf,max(l,ll[b+b+1]),r,b+b+1);
all[b]=all[b+b]+all[b+b+1];
}
int get(int l,int r,int b)
{
if(ll[b]==l&&rr[b]==r) return all[b].a[1][1];
Square d=aa[b];
aa[b]=S3;
aa[b+b]=aa[b+b]*d;
all[b+b]=all[b+b]*d;
aa[b+b+1]=aa[b+b+1]*d;
all[b+b+1]=all[b+b+1]*d;
int ans=0;
if(l<=rr[b+b]) ans+=get(l,min(r,rr[b+b]),b+b);
if(r>=ll[b+b+1]) ans+=get(max(l,ll[b+b+1]),r,b+b+1);
all[b]=all[b+b]+all[b+b+1];
if(ans>=P) ans-=P;
return ans;
}
signed main()
{
init();
int n,m;
scanf("%lld %lld",&n,&m);
while(m--)
{
int z,l,r,x;
scanf("%lld %lld %lld ",&z,&l,&r);
switch(z)
{
case 1:
{
scanf("%lld",&x);
add(1,x,l,r,1);
break;
}
case 2:
{
printf("%lld\n",get(l,r,1)%P);
break;
}
case 3:
{
scanf("%lld",&x);
add(3,x,l,r,1);
break;
}
case 4:
{
add(4,0,l,r,1);
break;
}
}
}
return 0;
}