bzoj4026
2015-07-22 22:26
295 查看
直接按照欧拉函数的计算方式来即可
φ=区间积*区间出现(质数-1)的积/区间出现过的质数的积
区间积是满足类似区间减法的操作的(利用逆元)
由于强制在线,上主席树就可以了(维护每个质数上次出现的位置pre,求区间[l,r],pre<l的元素即可)
View Code
φ=区间积*区间出现(质数-1)的积/区间出现过的质数的积
区间积是满足类似区间减法的操作的(利用逆元)
由于强制在线,上主席树就可以了(维护每个质数上次出现的位置pre,求区间[l,r],pre<l的元素即可)
const mo=1000777; type node=record po,next,num:longint; end; link=record l,r:longint; s1,s2:int64; end; var ni:array[0..mo] of int64; s,sd:array[0..50010] of int64; tree:array[0..50010*20*10] of link; p,v,last:array[0..1000010] of longint; e:array[0..500010] of node; h,a,q:array[0..50010] of longint; j,t,n,m,len,i,x,y,ans:longint; wh:int64; function build(l,r:longint):longint; var m,q:longint; begin inc(t); tree[t].s1:=1; tree[t].s2:=1; q:=t; if l<>r then begin m:=(l+r) shr 1; tree[q].l:=build(l,m); tree[q].r:=build(m+1,r); end; exit(q); end; function add(l,r,last,x,y:longint):longint; var m,q:longint; begin inc(t); q:=t; if l=r then begin tree[q].s1:=tree[last].s1*int64(y-1) mod mo; tree[q].s2:=tree[last].s2*ni[y] mod mo; end else begin m:=(l+r) shr 1; if x<=m then begin tree[q].r:=tree[last].r; tree[q].l:=add(l,m,tree[last].l,x,y); end else begin tree[q].l:=tree[last].l; tree[q].r:=add(m+1,r,tree[last].r,x,y); end; tree[q].s1:=tree[tree[q].l].s1*tree[tree[q].r].s1 mod mo; tree[q].s2:=tree[tree[q].l].s2*tree[tree[q].r].s2 mod mo; end; exit(q); end; function get(a,b:link):int64; var p1,p2:int64; begin p1:=b.s1*ni[a.s1] mod mo; p2:=b.s2*ni[a.s2] mod mo; exit(p1*p2 mod mo); end; function ask(l,r,x,y,z:longint):longint; var m:longint; p,q:int64; begin if z>=r then exit(get(tree[x],tree[y])) else begin m:=(l+r) shr 1; if z<=m then exit(ask(l,m,tree[x].l,tree[y].l,z)) else begin p:=get(tree[tree[x].l],tree[tree[y].l]); q:=ask(m+1,r,tree[x].r,tree[y].r,z); exit(p*q mod mo); end; end; end; begin for i:=2 to 1000000 do begin if v[i]=0 then begin inc(t); p[t]:=i; v[i]:=i; end; for j:=1 to t do begin if i*p[j]>1000000 then break; v[i*p[j]]:=p[j]; if i mod p[j]=0 then break; end; end; ni[1]:=1; for i:=2 to mo-1 do begin ni[i]:=-int64(mo div i)*ni[mo mod i] mod mo; if ni[i]<0 then ni[i]:=(ni[i]+mo) mod mo; end; readln(n,m); s[0]:=1; sd[0]:=1; for i:=1 to n do begin read(a[i]); s[i]:=s[i-1]*int64(a[i]) mod mo; sd[i]:=sd[i-1]*int64(ni[a[i]]) mod mo; x:=a[i]; while x<>1 do begin inc(len); y:=v[x]; e[len].po:=y; e[len].num:=last[y]; e[len].next:=q[i]; q[i]:=len; last[y]:=i; while x mod y=0 do x:=x div y; end; end; t:=0; tree[0].s1:=1; tree[0].s2:=1; h[0]:=build(0,n); for i:=1 to n do begin h[i]:=h[i-1]; j:=q[i]; while j<>0 do begin y:=e[j].po; h[i]:=add(0,n,h[i],e[j].num,y); j:=e[j].next; end; end; for i:=1 to m do begin readln(x,y); x:=x xor ans; y:=y xor ans; if x>y then begin t:=x; x:=y; y:=t; end; wh:=ask(0,n,h[x-1],h[y],x-1); ans:=wh*s[y] mod mo*sd[x-1] mod mo; if ans<0 then ans:=(ans+mo) mod mo; writeln(ans); end; end.
View Code
相关文章推荐
- 【攻克Android (6)】事件
- Red hat安装与使用
- C++析构函数
- 股票学习(K线分析03)孕线
- Python的高级特性9:蹩脚的多态
- 网络编程基础知识
- HTML标签自定义属性(转)
- java学习笔记一
- 文件复制实现
- .NET简谈路由事件
- HDU杭电 1039 Easier Done Than Said?(字符串问题)
- runtime-01
- (转)Android面试题
- 《慕客网:IOS基础入门之Foundation框架初体验》学习笔记 <五> NSDicionary + NSMutableDictionary
- MySQL - Incorrect string value: for column 'name' at row 1
- c.p.p第四章编程训练
- 事件和路由事件概述
- 内存分配、释放以及内存分配系统调用
- ffmpeg常用命令
- 黑马程序员------C语言基础 字符串