[清华集训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;
}
posted @ 2018-12-11 09:02  sdzwyq  阅读(215)  评论(0编辑  收藏  举报