题意:
给你n个数,每次有两种操作:
TOTIENT l r 问你从x到y区间
MULTIPLY l r x 将l到r的区间的值乘上x
题解:
对于欧拉函数来说
1.如果x,y互质
2.如果p是质数
那么乘上一个数我们可以用唯一分解定理将它分解变成1之后,再对每个质数用2去做。
但是很明显不能O(n)的去做,然后发现这个无所谓顺序并且可以合并,并且它还有区间更新区间查询,那么就考虑线段树优化。
并且我们知道第二个性质就是
,那么我们就只需要维护一下每种质数是否有,然后最后再乘个逆元什么的就行了。发现300之内的质数只有62个,于是用long long来存状态。于是线段树维护两个东西:当前区间有的值的状态,当前区间的答案。
时间复杂度极其差劲,用快读也要4700+,我估计是取模太多了,然后模乘也不知道怎么改才能在cf上用,有没有大佬知道取模优化方法的可以在下面留言
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pa pair<ll,ll>
const int N=4e5+5;
const ll mod=1e9+7;
ll p[N],np[N],cnt;
ll qpow(ll a,ll b){ll ans=1;for(;b;b>>=1,a=a*a%mod)if(b&1)ans=ans*a%mod;return ans;}
ll inv[65],inv1[65];
ll s[N*4],sum[N*4],f[N*4],fs[N*4],a[N];
void push_down(int l,int r,int root){
int mid=l+r>>1;
f[root<<1]=f[root<<1]*f[root]%mod;
fs[root<<1]|=fs[root];
f[root<<1|1]=f[root<<1|1]*f[root]%mod;
fs[root<<1|1]|=fs[root];
sum[root<<1]=sum[root<<1]*qpow(f[root],mid-l+1)%mod;
s[root<<1]|=fs[root];
sum[root<<1|1]=sum[root<<1|1]*qpow(f[root],r-mid)%mod;
s[root<<1|1]|=fs[root];
fs[root]=0;
f[root]=1;
}
void update(int l,int r,int root,int ql,int qr,ll v,ll msk){
if(l>=ql&&r<=qr){
f[root]=f[root]*v%mod;
fs[root]|=msk;
sum[root]=sum[root]*qpow(v,r-l+1)%mod;
s[root]|=msk;
return ;
}
int mid=l+r>>1;
push_down(l,r,root);
if(mid>=ql)
update(l,mid,root<<1,ql,qr,v,msk);
if(mid<qr)
update(mid+1,r,root<<1|1,ql,qr,v,msk);
s[root]=s[root<<1]|s[root<<1|1];
sum[root]=sum[root<<1]*sum[root<<1|1]%mod;
}
pa query(int l,int r,int root,int ql,int qr){
if(l>=ql&&r<=qr)
return {sum[root],s[root]};
int mid=l+r>>1;
push_down(l,r,root);
pa ans={1,0};
if(mid>=ql)
ans=query(l,mid,root<<1,ql,qr);
if(mid<qr){
pa ne=query(mid+1,r,root<<1|1,ql,qr);
ans.first=ans.first*ne.first%mod;
ans.second|=ne.second;
}
return ans;
}
char ss[25];
int main()
{
for(int i=2;i<=300;i++){
if(!np[i]){
p[cnt++]=i;
inv[cnt-1]=qpow(p[cnt-1],mod-2);
inv1[cnt-1]=qpow(p[cnt-1]-1,mod-2);
for(int j=i*i;j<=300;j+=i)
np[j]=1;
}
}
int n,q;
scanf("%d%d",&n,&q);
for(int i=1;i<=n*4;i++)
sum[i]=f[i]=1;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
if(a[i]==1)
continue;
ll msk=0;
for(int j=0;j<cnt;j++)
if(a[i]%p[j]==0)
msk|=(1ll<<j);
update(1,n,1,i,i,a[i],msk);
}
int l,r,v;
while(q--){
scanf("%s%d%d",ss,&l,&r);
if(ss[0]=='T'){
pa ans=query(1,n,1,l,r);
for(int i=0;i<cnt;i++)
if(ans.second&(1ll<<i))
ans.first=ans.first*(p[i]-1)%mod*inv[i]%mod;
printf("%lld\n",ans.first);
}
else{
scanf("%d",&v);
if(v==1)continue;
ll msk=0;
for(int j=0;j<cnt;j++)
if(v%p[j]==0)
msk|=(1ll<<j);
update(1,n,1,l,r,v,msk);
}
}
return 0;
}