1. 程式人生 > >[清華集訓2014]奇數國

[清華集訓2014]奇數國

[清華集訓2014]奇數國

luogu
UOJ
題意其實是讓單點修改,區間求\(\varphi\)
還保證分解之後只會有前60個質數
那麼用60個線段樹維護區間和即可
還有巧妙的做法是把60個質數是否存在壓在long long中線段樹維護
考試誰管那麼多...
然後BZOJ硬是T了...

#define ri register int
#define ls x<<1,l,mid
#define rs x<<1|1,mid+1,r
#define ll long long
#include<bits/stdc++.h>
using namespace std;
const int _=1e5+5,mod=19961993;
inline int re(){
    ri x=0,w=1;register char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return x*w;
}
int n=1e5,m;
int prime[66]={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};
int val[66],js[66],s[60][_<<2];
inline void pu(ri x){
    for(int i=0;i<60;i++)s[i][x]=s[i][x<<1]+s[i][x<<1|1];
}
void bu(ri x,ri l,ri r){
    if(l==r){s[1][x]=1;return;}
    ri mid=(l+r)>>1;bu(ls);bu(rs);
    s[1][x]=s[1][x<<1]+s[1][x<<1|1];
}
void upd(ri x,ri l,ri r,ri k){
    if(l==r){for(int i=0;i<60;i++)s[i][x]=val[i];return;}ri mid=(l+r)>>1;
    if(k<=mid)upd(ls,k);else upd(rs,k);pu(x);
}
void qsum(ri x,ri l,ri r,ri ql,ri qr){
    if(ql<=l&&r<=qr){for(int i=0;i<60;i++)js[i]+=s[i][x];return;}
    ri mid=(l+r)>>1;if(ql<=mid)qsum(ls,ql,qr);
    if(qr>mid)qsum(rs,ql,qr);
}
inline void mul(ri&x,ri y){x=1ll*x*y%mod;}
inline int ksm(ri x,ri y){
    ri s=1;
    while(y){if(y&1)mul(s,x);mul(x,x);y>>=1;}
    return s;
}
int main(){
    m=re();
    bu(1,1,n);
    while(m--){
        ri a=re(),b=re(),c=re();
        if(a){
            for(ri i=0;i<60;i++){
                val[i]=0;
                while(c%prime[i]==0){
                    val[i]++;c/=prime[i];
                }
            }
            upd(1,1,n,b);
        }
        else{
            ri ans=1;
            memset(js,0,sizeof(js));
            qsum(1,1,n,b,c);
            for(ri i=0;i<60;i++){
                if(!js[i])continue;
                if(js[i]>1)mul(ans,ksm(prime[i],js[i]-1));
                mul(ans,prime[i]-1);
            }
            printf("%d\n",ans);
        }
    }
    return 0;
}