您的位置:首页 > 其它

bzoj4026

2015-07-22 22:26 295 查看
直接按照欧拉函数的计算方式来即可

φ=区间积*区间出现(质数-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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: