奇数国[清华集训2014 Day1]

SOL

 奇奇怪怪的题目,我们发现我们的值对答案的贡献,发现其的大于281的质因数对答案无贡献,那么我们可以用一个60大小的数组来表示一个数。一个区间的答案就是其积的欧拉函数值,那么我们用树状数组维护。(常数有点大)

#pragma optimize("-O2")
#include<bits/stdc++.h>
#define LL long long
#define mo 19961993
#define getchar nc
#define N 100007
#define L(x) (x&-x)
#define sight(c) ('0'<=c&&c<='9')
#define bug 1000007
using namespace std;
int pim[60]={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};
inline char nc() {
static char buf[bug],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,bug,stdin),p1==p2)?EOF:*p1++; 
}
inline void read(int &x){
    static char c;static int b;
    for (b=1,c=getchar();!sight(c);c=getchar())if (c=='-')b=-1;
    for (x=0;sight(c);c=getchar()) x=x*10+c-48;
    x*=b;
}
inline void read(LL &x){
    static char c;static int b;
    for (b=1,c=getchar();!sight(c);c=getchar())if (c=='-')b=-1;
    for (x=0;sight(c);c=getchar()) x=x*10+c-48;
    x*=b;
}
void write(LL x) { if (x<10) { putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(LL x) {if (x<0) putchar('-'),x*=-1; write(x); putchar('\n');}
inline LL qsm(LL x,LL y){
    LL anw=1;
    for(;y;y>>=1,(x*=x)%=mo) if (y&1) (anw*=x)%=mo;
    return anw;
}
struct Seg{
    int t[60];
    inline LL ola(){
        LL an=1;
        for (int i=59;~i;i--) if (t[i]) (an*=(pim[i]-1)*qsm(pim[i],t[i]-1))%=mo;
        return an;
    }
    inline void rub(int x){
        memset(t,0,sizeof t);
        for (int i=59;~i;i--) while (!(x%pim[i])) t[i]++,x/=pim[i];
    }
    inline void operator += (const Seg& A){
        for (int i=59;~i;i--) t[i]+=A.t[i];
    }
    inline void operator -= (const Seg& A){
        for (int i=59;~i;i--) t[i]-=A.t[i];
    }
}S[N];
Seg opt,T,TT;
inline Seg operator +(const Seg &X,const Seg &Y){
    for (int i=59;~i;i--) T.t[i]=Y.t[i]+X.t[i]; return T;
}
inline Seg operator -(const Seg &X,const Seg &Y){
    for (int i=59;~i;i--) T.t[i]=X.t[i]-Y.t[i];  return T;
}
int tot,t[N];
Seg L;
void pre(){
    L.t[1]=1;
    for (int i=1;i<N;i++)  
        t[i]=3,S[i].t[1]=L(i);
}
int m,op,b,c;
Seg T1,T2;
int main () {
    pre();
    read(m); 
    while (m--) {
        read(op);
        switch (op) {
            case 0: read(b);read(c); 
            memset(opt.t,0,sizeof opt.t);
            for (int x=c;x;x-=L(x)) opt+=S[x];
            for (int x=b-1;x;x-=L(x)) opt-=S[x];
             writeln(opt.ola()); break;
            case 1: read(b); read(c);
             T1.rub(c); T2.rub(t[b]);
             L=T1-T2;
             for (int x=b;x<N;x+=L(x)) S[x]+=L; t[b]=c; break;
        }
    }
    return 0;
} 

 

posted @ 2018-01-10 19:59  泪寒之雪  阅读(222)  评论(0编辑  收藏  举报