如果题目不取模的话,就是一道裸的线段树区间求积。但现在加了取模的话,其实就是第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; }