乘除都在150以内,分解质因数后发现只有35个,建立35个树状数组/线段树,做区间加、区间查询,最后快速幂起来。
#include<cstdio> #include<cstring> using namespace std; #define N 50001 typedef long long ll; ll Quick_Pow(ll a,ll p,ll MOD) { if(!p) return 1; ll ans=Quick_Pow(a,p>>1,MOD); ans=ans*ans%MOD; if((p&1)==1) ans=ans*a%MOD; return ans; } int zu,n,m; int prime[151],en,zyz[151][40]; bool vis[151]; struct BIT { ll d[N]; void add_node(int p,const ll &v) {for(;p<=n;p+=(p&(-p)))d[p]+=v;} ll query(int p) {ll res=0;for(;p;p-=(p&(-p)))res+=d[p];return res;} void clear(){memset(d,0,sizeof(d));} }T[40]; struct BIT2 { ll d[N]; void add_node(int p,const ll &v) {for(;p<=n;p+=(p&(-p)))d[p]+=v;} void add_range(const int &L,const int &R,const ll &v) {add_node(L,v);if(R!=n)add_node(R+1,-v);} ll query(int p) {ll res=0;for(;p;p-=(p&(-p)))res+=d[p];return res;} void clear(){memset(d,0,sizeof(d));} }T2[40]; void Shai() { vis[1]=1; for(int i=2;i<=150;i++) { if(!vis[i]) prime[++en]=i; for(int j=i*i;j<=150;j+=i) vis[j]=1; } } void add(const int &wh,const int &p,const int &v) { T[wh].add_node(p,(ll)v*(ll)p); if(p!=1) T2[wh].add_range(1,p-1,(ll)v); } void Add(const int &wh,const int &L,const int &R,const int &v) { add(wh,R,v); if(L!=1) add(wh,L-1,(ll)(-v)); } ll query(const int &wh,const int &p) { return T[wh].query(p)+T2[wh].query(p)*(ll)p; } ll Query(const int &wh,const int &L,const int &R) { return query(wh,R)-(L==1?0:query(wh,L-1)); } ll QUERY(const int &wh,const int &L,const int &R) { if(L<=R) return Query(wh,L,R); else return Query(wh,L,n)+Query(wh,1,R); } int main() { int op,x,y,v; Shai(); for(int i=1;i<=150;++i) { int t=i; for(int j=1;j<=en;++j) while(t%prime[j]==0) { t/=prime[j]; ++zyz[i][j]; } } scanf("%d",&zu); for(;zu;--zu) { for(int i=1;i<=en;++i) { T[i].clear(); T2[i].clear(); } scanf("%d%d",&n,&m); for(;m;--m) { scanf("%d%d%d%d",&op,&x,&y,&v); if(op==1) { for(int i=1;i<=en;++i) if(zyz[v][i]) { if(x<=y) Add(i,x,y,zyz[v][i]); else { Add(i,x,n,zyz[v][i]); Add(i,1,y,zyz[v][i]); } } } else if(op==2) { for(int i=1;i<=en;++i) if(zyz[v][i]) { if(x<=y) Add(i,x,y,-zyz[v][i]); else { Add(i,x,n,-zyz[v][i]); Add(i,1,y,-zyz[v][i]); } } } else { ll ans=1; for(int i=1;i<=en;++i) ans=(ans*Quick_Pow((ll)prime[i],QUERY(i,x,y),(ll)v))%(ll)v; printf("%I64d\n",ans); } } } return 0; }
时间: 2024-10-05 04:43:00