清華集訓2014 奇數國
阿新 • • 發佈:2018-12-02
- 【清華集訓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; }