BZOJ3813奇数国 线段树+欧拉函数
Posted CQzhangyu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BZOJ3813奇数国 线段树+欧拉函数相关的知识,希望对你有一定的参考价值。
【BZOJ3813】奇数国
Description
给定一个序列,每次改变一个位置的数,或是询问一段区间的数的乘积的phi值。每个数都可以表示成前60个质数的若干次方的乘积。
Sample Input
6
0 1 3
1 1 5
0 1 3
1 1 7
0 1 3
0 2 3
0 1 3
1 1 5
0 1 3
1 1 7
0 1 3
0 2 3
Sample Output
18
24
36
6
24
36
6
HINT
x≤100000,当ai=0时0≤ci−bi≤100000
题解:显然我们可以先求出区间乘积,然后判断一下每个质数是否在其中出现过即可,如果出现过,则ans*=(P-1)/P。
由于只有60个质数,所以用一个long long存起来就行,然后用线段树维护一下。
#include <cstdio> #include <cstring> #include <iostream> #define lson x<<1 #define rson x<<1|1 using namespace std; typedef long long ll; const int maxn=100010; int n=100000,m,num; int pri[100],np[300]; ll ine[100]; const ll P=19961993; struct node { ll x,y; node() {} node(ll a,ll b) {x=a,y=b;} node operator + (const node &a) const {return node(x*a.x%P,y|a.y);} }s[maxn<<2]; inline int rd() { int ret=0,f=1; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) {if(gc==‘-‘) f=-f; gc=getchar();} while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+gc-‘0‘,gc=getchar(); return ret*f; } void build(int l,int r,int x) { if(l==r) { s[x]=node(3,2); return ; } int mid=(l+r)>>1; build(l,mid,lson),build(mid+1,r,rson); s[x]=s[lson]+s[rson]; } void updata(int l,int r,int x,int a,ll b) { if(l==r) { s[x]=node(b,0); for(int i=1;i<=60;i++) if(b%pri[i]==0) s[x].y|=(1ll<<(i-1)); return ; } int mid=(l+r)>>1; if(a<=mid) updata(l,mid,lson,a,b); else updata(mid+1,r,rson,a,b); s[x]=s[lson]+s[rson]; } node query(int l,int r,int x,int a,int b) { if(a<=l&&r<=b) return s[x]; int mid=(l+r)>>1; if(b<=mid) return query(l,mid,lson,a,b); if(a>mid) return query(mid+1,r,rson,a,b); return query(l,mid,lson,a,b)+query(mid+1,r,rson,a,b); } inline ll pm(ll x,ll y) { ll z=1; while(y) { if(y&1) z=z*x%P; x=x*x%P,y>>=1; } return z; } int main() { m=rd(); int i,j,a,b,op; for(i=2;i<=281;i++) { if(!np[i]) pri[++num]=i,ine[num]=pm(i,P-2); for(j=1;j<=num&&i*pri[j]<=281;j++) { np[i*pri[j]]=1; if(i%pri[j]==0) break; } } build(1,n,1); for(i=1;i<=m;i++) { op=rd(),a=rd(),b=rd(); if(!op) { node tmp=query(1,n,1,a,b); for(j=1;j<=60;j++) if((tmp.y>>(j-1))&1) tmp.x=tmp.x*ine[j]%P*(pri[j]-1)%P; printf("%lld\n",tmp.x); } else updata(1,n,1,a,b); } return 0; }//6 0 1 3 1 1 5 0 1 3 1 1 7 0 1 3 0 2 3
以上是关于BZOJ3813奇数国 线段树+欧拉函数的主要内容,如果未能解决你的问题,请参考以下文章