分析:
区间修改和单点查询可以用 实现,更简单。
欧拉定理拓展(欧拉降幂):
经过多次的 和 ,终于发现了问题的所在。关键在于当指数 和模数 的关系不同时,对其的操作也不同。
即代码如下:
ll Mod(ll x,ll y)//欧拉定理的判断条件 { return x>=y?(x%y+y):x; }
此外,本题为一个递归的过程,当借助快速幂来求一个数的幂,考虑到其可能作为另一个数的指数,所以对其取模时,同样不能乱取,也要按照上述的标准。
考虑到了这些,问题就很简单了。
代码:
#include <bits/stdc++.h> #define pb push_back using namespace std; const int N=5e5+5; const int maxn=2e7+5; typedef long long ll; ll bit[N]; int n; vector<int>prime; bool vis[maxn]; int phi[maxn]; void read(int &x) { x=0; int f=1; char ch=getchar(); while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)) { x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); } x*=f; } void init() { phi[1]=1; for(int i=2;i<maxn;i++) { if(!vis[i]) { prime.pb(i); phi[i]=i-1; } for(int j=0;j<prime.size()&&i*prime[j]<maxn;j++) { vis[i*prime[j]]=1; if(i%prime[j]==0) { phi[i*prime[j]]=phi[i]*prime[j]; break; } else phi[i*prime[j]]=phi[i]*phi[prime[j]]; } } } void update(int p,ll val) { while(p<=n) { bit[p]+=val; p+=(p&-p); } } ll query(int p) { ll res=0; while(p>0) { res+=bit[p]; p-=(p&-p); } return res; } void range_update(int l,int r,ll val) { update(l,val); update(r+1,-val); } ll Mod(ll x,ll y)//欧拉定理的判断条件 { return x>=y?(x%y+y):x; } ll power(ll a,ll b,ll p) { ll res=1; a=Mod(a,p); while(b) { if(b&1) res=Mod(res*a,p); a=Mod(a*a,p); b>>=1; } return res; } ll dfs(int v,int p,int r) { ll tn=query(v); if(v==r||p==1) return Mod(tn,1LL*p); ll res=dfs(v+1,phi[p],r);//保留原始值 return power(tn,res,1LL*p); } int main() { init(); int m,a,op,l,r,x,p; read(n),read(m); for(int i=1;i<=n;i++) { read(a); range_update(i,i,a); } while(m--) { read(op),read(l),read(r); if(op==1) { read(x); range_update(l,r,1LL*x); } else { read(p); printf("%lld\n",dfs(l,p,r)%p); } } return 0; }