题意:
给定长度为n的序列a,q次操作,操作有两种:
1.将[L,R]所有数乘上x
2.查询[L,R]区间乘积的欧拉函数值
答案对1e9+7取模
数据范围:n<=4e5,q<=2e5,1<=a(i),x<=300
解法:
欧拉函数拆分:
这道题选用最后一个式子,因为最后一个式子中的(p-1)/p可以预处理,那么只需要维护区间乘积n就行了
维护乘积显然线段树
打表观察到300以内只有62个质数,再状压一个二进制数,维护区间内出现过哪些质数即可
code:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
//
const int maxm=4e5+5;
const int mod=1e9+7;
//
int ppow(int a,int b,int mod){
int ans=1%mod;a%=mod;
while(b){
if(b&1)ans=1LL*ans*a%mod;
a=1LL*a*a%mod;
b>>=1;
}
return ans;
}
//
int p[105],cnt;
int inv[105];
bool isprime(int x){
for(int i=2;i*i<=x;i++){
if(x%i==0)return 0;
}
return 1;
}
void init(){
for(int i=2;i<=300;i++){
if(isprime(i)){
inv[cnt]=1LL*(i-1)*ppow(i,mod-2,mod)%mod;
p[cnt++]=i;
}
}
}
//
int a[maxm<<2];
int laz[maxm<<2];
ll flaz[maxm<<2];
ll flag[maxm<<2];
void pushup(int node){
flag[node]=(flag[node*2]|flag[node*2+1]);
a[node]=1LL*a[node*2]*a[node*2+1]%mod;
}
void pushdown(int node,int l,int r){
if(laz[node]!=1){
int mid=(l+r)/2;
a[node*2]=1LL*a[node*2]*ppow(laz[node],mid-l+1,mod)%mod;
a[node*2+1]=1LL*a[node*2+1]*ppow(laz[node],r-mid,mod)%mod;
laz[node*2]=1LL*laz[node*2]*laz[node]%mod;
laz[node*2+1]=1LL*laz[node*2+1]*laz[node]%mod;
laz[node]=1;
}
if(flaz[node]){
flag[node*2]|=flaz[node];
flag[node*2+1]|=flaz[node];
flaz[node*2]|=flaz[node];
flaz[node*2+1]|=flaz[node];
flaz[node]=0;
}
}
void build(int l,int r,int node){
laz[node]=1;
if(l==r){
scanf("%d",&a[node]);
flag[node]=0;
for(int i=0;i<62;i++){
if(a[node]%p[i]==0){
flag[node]|=(1LL<<i);
}
}
return ;
}
int mid=(l+r)/2;
build(l,mid,node*2);
build(mid+1,r,node*2+1);
pushup(node);
}
void update(int st,int ed,int val,int l,int r,int node){
if(st<=l&&ed>=r){
a[node]=1LL*a[node]*ppow(val,r-l+1,mod)%mod;
laz[node]=1LL*laz[node]*val%mod;
for(int i=0;i<62;i++){
if(val%p[i]==0){
flag[node]|=(1LL<<i);
flaz[node]|=(1LL<<i);
}
}
return ;
}
pushdown(node,l,r);
int mid=(l+r)/2;
if(st<=mid)update(st,ed,val,l,mid,node*2);
if(ed>mid)update(st,ed,val,mid+1,r,node*2+1);
pushup(node);
}
pair<int,ll> ask(int st,int ed,int l,int r,int node){
if(st<=l&&ed>=r){
return {a[node],flag[node]};
}
pushdown(node,l,r);
int mid=(l+r)/2;
pair<int,ll>ans={1,0},temp;
if(st<=mid){
temp=ask(st,ed,l,mid,node*2);
ans.first=1LL*ans.first*temp.first%mod;
ans.second|=temp.second;
}
if(ed>mid){
temp=ask(st,ed,mid+1,r,node*2+1);
ans.first=1LL*ans.first*temp.first%mod;
ans.second|=temp.second;
}
return ans;
}
//
char s[100];
int n,q;
signed main(){
init();
//
scanf("%d%d",&n,&q);
build(1,n,1);
while(q--){
scanf("%s",s);
if(s[0]=='M'){
int l,r,x;scanf("%d%d%d",&l,&r,&x);
update(l,r,x,1,n,1);
}else if(s[0]=='T'){
int l,r;scanf("%d%d",&l,&r);
pair<int,ll>ans=ask(l,r,1,n,1);
int res=ans.first;
for(int i=0;i<62;i++){
if(ans.second>>i&1){
res=1LL*res*inv[i]%mod;
}
}
printf("%d\n",res);
}
}
return 0;
}