如果题目不取模的话,就是一道裸的线段树区间求积。但现在加了取模的话,其实就是第2种操作的时候乘上 的逆元即可。逆元费马小定理就可以。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;
const int mod=1e9+7;
int n,m;
ll a[maxn];
struct node{
int l,r;
ll w;
}t[maxn<<2];
ll qpow(ll x,ll y)//快速幂求逆元
{
ll ans=1;
while(y)
{
if(y&1)ans=(ans*x)%mod;
y>>=1; x=(x*x)%mod;
}
return ans;
}
void pushup(int k)
{
t[k].w=t[k<<1].w*t[k<<1|1].w%mod;
}
void build(int k,int l,int r)
{
t[k].l=l,t[k].r=r;
if(l==r){t[k].w=a[l];return;}
int mid=l+r>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pushup(k);
}
void update(int k,int x,ll y)
{
if(t[k].l==t[k].r){t[k].w=t[k].w*y%mod;return;}
int mid=t[k].l+t[k].r>>1;
if(x<=mid)update(k<<1,x,y);
else update(k<<1|1,x,y);
pushup(k);
}
ll query(int k,int l,int r)
{
int x=t[k].l,y=t[k].r;
if(l<=x&&y<=r)return t[k].w;
int mid=x+y>>1;
ll ans=1;
if(l<=mid)ans=ans*query(k<<1,l,r)%mod;
if(mid<r)ans=ans*query(k<<1|1,l,r)%mod;
return ans;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++)a[i]=1;
build(1,1,n);
for(int i=1;i<=m;i++)
{
int op,x,y; cin>>op>>x>>y;
if(op==1)update(1,x,y);
else if(op==2)update(1,x,qpow(y,mod-2));
else cout<<query(1,x,y)<<"\n";
}//全程记得取模就行
return 0;
} 
京公网安备 11010502036488号