输入输出样例
输入样例#1: 复制
6 4 1 2 3 4 5 6 2 1 2 10000007 2 2 3 5 1 1 4 1 2 2 4 10
输出样例#1: 复制
1 3 1
输入样例#2: 复制
5 5 2 3 3 3 3 1 1 1 530739835 2 1 1 8356089 2 1 4 5496738 1 1 2 66050181 1 2 4 138625417
输出样例#2: 复制
4306230 697527
先粘题解,以后再来解决这个常数,实在受不了了
#include<bits/stdc++.h>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define bug(x) printf("****%d\n",x)
typedef long long ll;
using namespace std;
const int maxn=5e5+10;
ll val[maxn];
const int lim=2e7+10;
/*
ll phi[lim];
void get_phi(){
phi[0]=1;
for(int i=2;i<lim;i++){
if(!phi[i]){
for(int j=i;j<lim;j+=i){
if(!phi[j])phi[j]=j;
phi[j]-=phi[j]/i;
}
}
}
}
*/
ll phi[lim],prime[lim],cnt=0;
bool vis[lim];
inline void calcpri(){
phi[1]=1;
for(int i=2;i<=lim;i++){
if(!vis[i])prime[++cnt]=i,phi[i]=i-1;
for(int j=1;j<=cnt;j++){
int t=i*prime[j];if(t>lim)break;
vis[t]=1;
if(i%prime[j]==0){phi[t]=phi[i]*prime[j];break;}
phi[t]=phi[i]*(prime[j]-1);
}
}
}
ll pow_(ll base,ll n,ll mod){
ll ans=1;
while(n){
if(n&1)
ans=ans*base%mod;
n>>=1;
base=base*base%mod;
}
return ans%mod;
}
struct node{
int l,r;
int lazy;
ll sum,tag;
}tr[maxn<<2];
void pushup(int o){
tr[o].sum=tr[ls(o)].sum+tr[rs(o)].sum;
}
void pushdown(int o){
tr[ls(o)].tag+=tr[o].tag;
tr[rs(o)].tag+=tr[o].tag;
tr[o].lazy=0;
tr[o].tag=0;
tr[ls(o)].lazy=tr[rs(o)].lazy=1;
}
void build(int l,int r,int o){
tr[o].l=l,tr[o].r=r;
tr[o].lazy=tr[o].tag=0;
if(l==r){
tr[o].sum=val[l];
return;
}
int mid=(tr[o].l+tr[o].r)>>1;
build(l,mid,ls(o));
build(mid+1,r,rs(o));
pushup(o);
}
void update(int l,int r,ll val,int o){
if(tr[o].l>=l&&tr[o].r<=r){
tr[o].tag+=val;
tr[o].lazy=1;
return;
}
if(tr[o].lazy) pushdown(o);
int mid=(tr[o].l+tr[o].r)>>1;
if(r<=mid)update(l,r,val,ls(o));
else if(l>mid)update(l,r,val,rs(o));
else{
update(l,mid,val,ls(o));
update(mid+1,r,val,rs(o));
}
pushup(o);
}
ll query(int pos,int o){
if(tr[o].l==tr[o].r){
return tr[o].sum+tr[o].tag;
}
if(tr[o].lazy)pushdown(o);
int mid=(tr[o].l+tr[o].r)>>1;
if(pos<=mid)
return query(pos,ls(o));
else
return query(pos,rs(o));
}
ll rec[maxn];
int n,m;
ll Query(int pos,int o){//优化,保存 val[] 最后在哪一次修改
if(rec[pos]==m) return val[pos];
rec[pos]=m;
return val[pos]=query(pos,o);
}
ll cal(int l,int r,ll p){
if(Query(l,1)%p==0)return 0;//优化
if(p==1) return 1;
if(l==r)return Query(l,1)%p+(Query(l,1)>=p)*p;//不能不写后面
int f=min(r,l+5);//计算最高五层的 幂值
for(int i=l+1;i<=f;i++){//优化
if(Query(i,1)==1){//上面就是1^?===1
f=i;break;
}
}
ll ans=Query(f,1),q;
for(int i=f-1;i>l;i--){//为了验证指数是否 大于 phi[p]
q=ans;
ans=1;
while(q--){
ans*=Query(i,1);
if(ans>=phi[p])return pow_(Query(l,1)%p,cal(l+1,r,phi[p])+phi[p],p);
}
}
return pow_(Query(l,1)%p,ans,p);
}
/*
6 4
1 2 3 4 5 6
2 2 3 5
2 1 2 10000007
1 1 4 1
2 2 4 10
*/
inline ll read(){
ll f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
int main(){
memset(rec,-1,sizeof(rec));
//get_phi();
calcpri();
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%lld",&val[i]);
}
build(1,n,1);
while(m--){
int t,l,r;ll x;
//t=read(),l=read(),r=read(),x=read();
scanf("%d %d %d %lld",&t,&l,&r,&x);
if(t==1)
update(l,r,x,1);
else{
ll ans=cal(l,r,x)%x;
printf("%lld\n",ans);
}
}
return 0;
}