BZOJ 4026 dC Loves Number Theory 主席树
题目大意:中文题自己看
首先phi[i] = i * (1 - p1) ... * (1 - pn)
由于每一个质因数p只用了一次,所以对区间做HH 的项链就好了.
PS: 我真是太弱了,差点写吐了QAQ...
#include <stdio.h> #include <cstring> #include <iostream> #include <algorithm> typedef long long ll; #define N 1000000UL #define MAXN 50005UL #define mod 1000777UL int n,Q,prime[1000005],tot,last[1000005],val[MAXN]; bool _prime[1000005]; ll Ans,use[1000005],fac[MAXN]; template<typename _t> inline _t read(){ _t x=0,f=1; char ch=getchar(); for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f=-f; for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+(ch^48); return x*f; } inline ll qpow(ll x,ll k){ ll Ans = 1; for(;k;k>>=1,x = 1ll * x * x % mod) if(k&1) Ans = Ans * x % mod; return Ans; } int first[1000005],e = 1; struct edge{ int u,v,next; }a[3000005]; inline void push(int u,int v){ a[e].u=u;a[e].v=v;a[e].next=first[u];first[u]=e++; } inline void init(){ for(int i = 2;i<=N;i++) { if(!_prime[i]) { prime[++tot] = i; for(int j = i;j<=N;j+=i){ _prime[j] = 1; push(j,tot); } } } for(int i = 1;i<=tot;i++) use[i] = 1ll * (prime[i]-1) * qpow(prime[i],mod-2) % mod; } namespace CMT{ int root[MAXN],cnt; struct node{ int l,r; ll sum; }tree[MAXN*100]; inline void build(int &o,int l,int r){ o = ++ cnt; tree[o].sum = 1; if(l == r) return; register int mid = l + r >> 1; build(tree[o].l,l,mid);build(tree[o].r,mid+1,r); } inline void Update(int &o,int old,int l,int r,int x,ll val){ o = ++ cnt; tree[o] = tree[old]; tree[o].sum = tree[old].sum * val % mod; if(l == r) return; register int mid = l + r >> 1; if(x<=mid) Update(tree[o].l,tree[old].l,l,mid,x,val); else Update(tree[o].r,tree[old].r,mid+1,r,x,val); } inline ll Query(int o,int l,int r,int x,int y){ if(x<=l&&r<=y) return tree[o].sum; register int mid = l + r >> 1; ll Ans = 1; if(x<=mid) Ans = Ans * Query(tree[o].l,l,mid,x,y) % mod; if(mid<y) Ans = Ans * Query(tree[o].r,mid+1,r,x,y) % mod; return Ans; } } using namespace CMT; inline void work(int x,int id){ int num = root[id - 1]; ll sum = 1; for(int i = first[x];i;i=a[i].next) { if(x%prime[a[i].v] == 0){ while(x % prime[a[i].v] == 0) x /= prime[a[i].v]; if(last[prime[a[i].v]]) Update(num,num,1,n,last[prime[a[i].v]],qpow(use[a[i].v],mod-2)); last[prime[a[i].v]] = id; sum = sum * use[a[i].v] % mod; } } Update(root[id],num,1,n,id,sum); } inline void Query(){ register int l = read<int>() ^ Ans , r = read<int>() ^ Ans; Ans = Query(root[r],1,n,l,r); Ans = Ans * fac[r] % mod * qpow(fac[l-1],mod-2) % mod; printf("%lld\n",Ans); } int main(){ init(); n = read<int>();Q = read<int>(); fac[0] = 1;build(root[0],1,n); for(int i = 1;i<=n;i++) val[i] = read<int>(),fac[i] = fac[i-1] * val[i] % mod; for(int i = 1;i<=n;i++) work(val[i],i); while(Q --) Query(); return 0; }