https://codeforces.com/contest/1114/problem/F
操作二,维护区间乘积的值的欧拉值
p是的质因数
操作一,懒标记乘300以内的数,维护ai也是300以内的数
因此我们只要维护300以内的质数的状态就可以了
用埃氏筛来筛出300以内的质数
因此我们维护300以内的质数的状态,以及区间乘积,懒标记(乘法标记,标记值x的质因数有哪些)
维护操作就是区间或,区间乘
思路很明了,操作有点复杂
而且需要优化
我们考虑优化质数状态,通过筛法得知300以内有62个质数,可以状态压缩到一个long long 数的二进制位上,如果超过ll,可以开bitset空间优化成 (n/32)
在计算的结果的时候要求逆元,对与mod数较大(mod>1e7) O(logb)的,我们可以线性求逆元
实际上更大的优化是线段树不要用结构体,写几个数组就可以了,但是个人不是很好看
code
// Problem: F. Please, another Queries on Array?
// Contest: Codeforces - Codeforces Round 538 (Div. 2)
// URL: https://codeforces.com/problemset/problem/1114/F
// Memory Limit: 256 MB
// Time Limit: 5500 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<iostream>
#include<bitset>
using namespace std;
typedef long long ll;
typedef long long LL;
const int N=4e5+9;
const int mod=1e9+7;
const int ZS=65;//300内质数数量62,开大点防止越界
const int p[65]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293};
int pp[500];//映射
int inv[500],f[65];
//modint
int ADD(int a, int b){return (a + b) % mod;}
int MUL(int a, int b){return 1ll * a * b % mod;}
int SUB(int a, int b){return ((a - b) % mod + mod) % mod;}
//
int a[N];
ll qmi(ll a,ll b){
ll res=1;
while(b){
if(b&1){
res=res*a%mod;
}
a=a*a%mod;
b>>=1;
}
return res;
}
//处理质数 300 打表
bitset<500> prime;
void init(){
// prime[1]=1;
// for(int i=2;i<=300/i;i++){
// if(!prime[i]){
// for(int j=2*i;j<=300;j+=i){
// prime[j]=1;
// }
// }
// }
// for(int i=1;i<=300;i++){
// if(!prime[i]){
// cout<<i<<',';
// }
// }
// cout<<'\n';
//映射index
for(int i=1;i<=62;i++){
pp[p[i]]=i;
}
//线性处理逆元O(n)
inv[1]=1;
for(int i=2;i<=301;i++){
inv[i]=MUL(inv[mod%i],(mod-mod/i));
}
for(int i=1;i<=62;i++){
f[i]=MUL((p[i]-1),inv[p[i]]);
}
}
//线段树
struct SEG{
#define INF (1ll<<63)
#define ll long long
#define tl(id) (id<<1)
#define tr(id) (id<<1|1)
#define li inline
struct Info{//信息
ll num;//状态压缩,状态量超过63可以用bitset
int cfval;//乘积
li Info friend operator + (const Info &a,const Info &b){//合并改
Info res;
res.num=a.num|b.num;
res.cfval=MUL(a.cfval,b.cfval);
return res;
}
};
struct Tag{//标记
ll tag;
ll mul;//乘法标记
Tag(){init();}
li void init(){//初始化改
mul=1;
tag=0;
//都是0
}
li Tag friend operator + (const Tag &a,const Tag &b){//增加质因数
Tag t;
t.tag=a.tag|b.tag;
t.mul=MUL(a.mul,b.mul);
return t;
}
};
struct node{
int l,r;
Info val;
Tag lazy;
}seg[N<<2];
#define pushup(id) seg[id].val=seg[tl(id)].val+seg[tr(id)].val;
li int inrange(int L,int R,int l,int r){return l<=L && R<=r;}
li int outofrange(int L,int R,int l,int r){return L>r || R<l;}
li void build(const int id,int l,int r){
seg[id].l=l,seg[id].r=r;
seg[id].lazy.init();//初始化
if(l==r){
//质因数分解
seg[id].val.cfval=a[l];
if(a[l]==1){
return;
}
int x=a[l];
for(int i=2;i<=x/i;i++){
if(x%i==0){
while(x%i==0){
x/=i;
}
seg[id].val.num|=(1ll<<pp[i]);
}
}
if(x>1){
seg[id].val.num|=(1ll<<pp[x]);
}
return;
}
int mid=(l+r)>>1;
build(tl(id),l,mid);
build(tr(id),mid+1,r);
pushup(id);
}
li void maketag(int id,int l,int r,Tag v){
seg[id].val.num|=v.tag;
seg[id].val.cfval=MUL(seg[id].val.cfval,qmi(v.mul,r-l+1));//维护区间乘积
seg[id].lazy=seg[id].lazy+v;
}
li void pushdown(int id,int l,int r){
int mid=(l+r)>>1;
maketag(tl(id),l,mid,seg[id].lazy);
maketag(tr(id),mid+1,r,seg[id].lazy);
seg[id].lazy.init();//初始化
}
li Info query(int id,int l,int r){
if(inrange(seg[id].l,seg[id].r,l,r)){
return seg[id].val;
}else{
int mid=(seg[id].l+seg[id].r)>>1;
pushdown(id,seg[id].l,seg[id].r);
if(mid>=r){
return query(tl(id),l,r);
}else if(mid<l){
return query(tr(id),l,r);
}else{
return (query(tl(id),l,mid)+query(tr(id),mid+1,r));
}
}
}
li void modify(int id,int L,int R,int l,int r,Tag x){
if(inrange(L,R,l,r)){
maketag(id,L,R,x);
}else if(!outofrange(L,R,l,r)){
int mid=(L+R)>>1;
pushdown(id,L,R);
modify(tl(id),L,mid,l,r,x);
modify(tr(id),mid+1,R,l,r,x);
pushup(id);
}
}
}t;
SEG::Tag v;
//处理修改的x
void pre(int x){
v.mul=x;
v.tag=0;
for(int i=2;i<=x/i;i++){
if(x%i==0){
while(x%i==0){
x/=i;
}
v.tag|=(1ll<<pp[i]);
}
}
if(x>1){
v.tag|=(1ll<<pp[x]);
}
}
#define Tag SEG::Tag
#define Info SEG::Info
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
init();
int n,q;
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
}
t.build(1,1,n);
for(int i=1;i<=q;i++){
string op;
cin>>op;
if(op[0]=='M'){
int l,r,x;
cin>>l>>r>>x;
pre(x);
t.modify(1,1,n,l,r,v);
}else{
int l,r;
cin>>l>>r;
Info res=t.query(1,l,r);
ll ans=res.cfval;
for(int i=1;i<=62;i++){
if(res.num&(1ll<<i)){
ans=MUL(ans,f[i]);
}
}
cout<<(ans%mod+mod)%mod<<'\n';
}
// for(int i=1;i<=n;i++){
// Info ans=t.query(1,i,i);
// cout<<"cfval"<<" "<<ans.cfval<<'\n';
// cout<<i<<" "<<"质因数"<<'\n';
// for(int i=1;i<=62;i++){
// if(ans.num&(1ll<<i)){
// cout<<p[i]<<" ";
// }
// }
// cout<<'\n';
// }
// cout<<'\n';
// cout<<'\n';
// cout<<'\n';
// cout<<'\n';
}
}