清华集训2014 奇数国

  • 【清华集训2014】奇数国
  • 欧拉函数+线段树,傻逼题……。
  • 首先那个\(ax+by=1\)就是在搞笑,想一想有整数的条件就是\(gcd(a,b)=1\),实际上是让你求\(\phi\)
  • 所以现在需要支持两种操作,区间积求\(phi\),单点修改。
  • 因为每个数都只有最多\(60\)个不同质因子,所以可以把它分解质因数。
  • 然后就能用\(60\)个线段树来维护每个质因子个数。
  • 询问是求区间乘积的欧拉函数,然后用公式\(\phi_n=n*\prod(1-\frac {1}{p_i})\)就可以了。
  • 复杂度\(O(60*qlogn)\)
  • 线段树可以换成树状数组,常数小很多。
#include<bits/stdc++.h>
#define R register int
#define db double
#define ll long long 
using namespace std;
const int N=100001;
const int mod=19961993;
int n,m,op,u,v,ans;
int gi(){
    R x=0,k=1;char c=getchar();
    while(c!='-'&&(c<'0'||c>'9'))c=getchar();
    if(c=='-')k=-1,c=getchar();
    while(c<='9'&&c>='0')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x*k;
}
namespace cpp1{
    int tot,mk[N],prm[N];
    struct mon{
        int s[61];
        void init(){memset(s,0,sizeof(s));}
    }te[N*4],nw;
    int Qpow(R x,R y){
        R ans=1,bas=x;
        while(y){
            if(y&1)ans=1ll*ans*bas%mod;
            bas=1ll*bas*bas%mod,y>>=1;
        }return ans;
    }
    mon mul(mon x,mon y){
        mon z;
        for(R i=1;i<=60;++i)z.s[i]=x.s[i]+y.s[i];
        return z;
    }
    mon rev(R x){
        mon z;z.init();
        for(R j=1;j<=tot;++j){
            while(x%prm[j]==0)
                z.s[j]++,x/=prm[j];
        }
        return z;
    }
    void init(){
        mk[0]=mk[1]=1;
        for(R i=2;i<N;++i){
            if(!mk[i])prm[++tot]=i;
            for(R j=1;j<=tot&&i*prm[j]<N;++j){
                mk[i*prm[j]]=1;
                if(i%prm[j]==0)break;
            }
        }tot=60;
    }
    void upd(R Le,R Ri,R ps,R i){
        if(Le==Ri){te[i]=nw;return ;}
        R mid=(Le+Ri)>>1,ls=(i<<1),rs=(ls|1);
        if(ps<=mid)upd(Le,mid,ps,ls);else upd(mid+1,Ri,ps,rs);
        te[i]=mul(te[ls],te[rs]);
    }
    mon query(R Le,R Ri,R le,R ri,R i){
        if(Le==le&&Ri==ri)return te[i];
        R mid=(Le+Ri)>>1,ls=(i<<1),rs=(ls|1);
        if(ri<=mid)return query(Le,mid,le,ri,ls);
        else if(le>mid)return query(mid+1,Ri,le,ri,rs);
        else return mul(query(Le,mid,le,mid,ls),query(mid+1,Ri,mid+1,ri,rs));
    }
    void Main(){
        n=100000,m=gi(),init(),nw.init(),nw.s[2]=1;
        for(R i=1;i<=n;++i)upd(1,n,i,1);
        while(m--){
            op=gi(),u=gi(),v=gi();
            if(op==1)nw=rev(v),upd(1,n,u,1);
            else {
                nw=query(1,n,u,v,1),ans=1;
                for(R j=1;j<=60;++j)
                    if(nw.s[j]){
                        ans=1ll*ans*(prm[j]-1)%mod;
                        ans=1ll*ans*Qpow(prm[j],nw.s[j]-1)%mod;
                    }
                printf("%d\n",ans);
            }
        }
    }
}
int main(){
    cpp1::Main();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Tyher/p/10054133.html