可能是这天 真的状态太差了 写了一半居然怀疑复杂度 没写了。。。
我们对于每一个因子分开去维护
对于一个数x = p1c1p2c2p3C3…
每一个因子的欧拉函数为
p1c1 (p1-1)/p1
如果第一次修改当前因子
那么乘上p1c1(p-1)/p
如果有了直接乘上p1^c1
欧拉函数是奇性函数如果p q互质那么pq的欧拉函数就是p的欧拉函数*q的欧拉函数
想清楚发现 对于每个点最多单点修改25次
明明在比赛中敲了一半多了 自己把他放弃
贴一下ac代码给大家看看
100以内一共25个质数
然后用二进制表示每一位有没有存在
如果向下修改的那个状态和这段区间有差别 那么直接暴力修改这一段
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1e6+10,mod=998244353;
typedef long long LL;
int a[N],st[N];
int t[N];
struct Node{
int l,r;
LL tag,sum,val,cnt;
void change(LL k1){
tag*=k1;
tag%=mod;
sum=k1%mod*sum%mod;
}
}tr[N<<2];
int p[N],cnt;
LL qpow(LL x,LL k){
LL res=1;
while(k){
if(k&1)res=res*x%mod;
x=x*x%mod;
k>>=1;
}
return res;
}
void push_up(int u){
tr[u].cnt=(tr[u<<1].cnt&tr[u<<1|1].cnt);
tr[u].sum=(tr[u<<1].sum+tr[u<<1|1].sum)%mod;
}
void build(int u,int l,int r){
tr[u]={l,r,1,1,1,1};
if(l==r){
tr[u].sum=a[l];
for(int i=1;i<=cnt;i++){
if(a[l]%p[i]==0){
tr[u].cnt|=1<<i;
tr[u].sum*=t[i];
tr[u].sum%=mod;
}
}
return ;
}
int mid=l+r>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
push_up(u);
}
void push_down(int u){
if(tr[u].tag!=1){
tr[u<<1].change(tr[u].tag);
tr[u<<1|1].change(tr[u].tag);
tr[u].tag=1;
}
}
void change(int u,int l,int r,LL k1,LL k2){
if(tr[u].l>r||tr[u].r<l)return ;
if(l<=tr[u].l&&tr[u].r<=r&&((tr[u].cnt&k2)==k2)){
tr[u].change(k1);
return ;
}
if(tr[u].l==tr[u].r){
tr[u].sum*=k1;
tr[u].sum%=mod;
for(int i=1;i<=cnt;i++){
if((k2>>i&1)&&(!(tr[u].cnt>>i&1))){
tr[u].sum*=t[i];
tr[u].sum%=mod;
tr[u].cnt|=1<<i;
}
}
return ;
}
push_down(u);
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid)change(u<<1,l,r,k1,k2);
if(r>mid)change(u<<1|1,l,r,k1,k2);
push_up(u);
}
LL query(int u,int l,int r){
if(l<=tr[u].l&&tr[u].r<=r){
return tr[u].sum;
}
push_down(u);
int mid=tr[u].l+tr[u].r>>1;
long long sum=0;
if(l<=mid)sum+=query(u<<1,l,r);
if(r>mid)sum+=query(u<<1|1,l,r);
sum%=mod;
push_up(u);
return sum;
}
int main(){
for(int i=2;i<=100;i++){
if(!st[i]){
p[++cnt]=i;
t[cnt]=(i-1)*qpow(i,mod-2)%mod;
}
for(int j=i;j<=100;j+=i){
st[j]=1;
}
}
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
build(1,1,n);
for(int i=1;i<=m;i++){
int op,l,r,x;
scanf("%d%d%d",&op,&l,&r);
if(op==1){
printf("%lld\n",query(1,l,r));
}else{
scanf("%d",&x);
LL tt=0;
for(int j=1;j<=cnt;j++){
if(x%p[j]==0){
tt|=1<<j;
}
}
change(1,l,r,x,tt);
}
}
return 0;
}