分析:
区间修改和单点查询可以用 实现,更简单。
欧拉定理拓展(欧拉降幂):
经过多次的 和
,终于发现了问题的所在。关键在于当指数
和模数
的关系不同时,对其的操作也不同。
即代码如下:
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;
}

京公网安备 11010502036488号