zoukankan      html  css  js  c++  java
  • bzoj4026

    直接按照欧拉函数的计算方式来即可

    φ=区间积*区间出现(质数-1)的积/区间出现过的质数的积

    区间积是满足类似区间减法的操作的(利用逆元)

    由于强制在线,上主席树就可以了(维护每个质数上次出现的位置pre,求区间[l,r],pre<l的元素即可)

      1 const mo=1000777;
      2 type node=record
      3        po,next,num:longint;
      4      end;
      5      link=record
      6        l,r:longint;
      7        s1,s2:int64;
      8      end;
      9 
     10 var ni:array[0..mo] of int64;
     11     s,sd:array[0..50010] of int64;
     12     tree:array[0..50010*20*10] of link;
     13     p,v,last:array[0..1000010] of longint;
     14     e:array[0..500010] of node;
     15     h,a,q:array[0..50010] of longint;
     16     j,t,n,m,len,i,x,y,ans:longint;
     17     wh:int64;
     18 
     19 function build(l,r:longint):longint;
     20   var m,q:longint;
     21   begin
     22     inc(t);
     23     tree[t].s1:=1;
     24     tree[t].s2:=1;
     25     q:=t;
     26     if l<>r then
     27     begin
     28       m:=(l+r) shr 1;
     29       tree[q].l:=build(l,m);
     30       tree[q].r:=build(m+1,r);
     31     end;
     32     exit(q);
     33   end;
     34 
     35 function add(l,r,last,x,y:longint):longint;
     36   var m,q:longint;
     37   begin
     38     inc(t);
     39     q:=t;
     40     if l=r then
     41     begin
     42       tree[q].s1:=tree[last].s1*int64(y-1) mod mo;
     43       tree[q].s2:=tree[last].s2*ni[y] mod mo;
     44     end
     45     else begin
     46       m:=(l+r) shr 1;
     47       if x<=m then
     48       begin
     49         tree[q].r:=tree[last].r;
     50         tree[q].l:=add(l,m,tree[last].l,x,y);
     51       end
     52       else begin
     53         tree[q].l:=tree[last].l;
     54         tree[q].r:=add(m+1,r,tree[last].r,x,y);
     55       end;
     56       tree[q].s1:=tree[tree[q].l].s1*tree[tree[q].r].s1 mod mo;
     57       tree[q].s2:=tree[tree[q].l].s2*tree[tree[q].r].s2 mod mo;
     58     end;
     59     exit(q);
     60   end;
     61 
     62 function get(a,b:link):int64;
     63   var p1,p2:int64;
     64   begin
     65     p1:=b.s1*ni[a.s1] mod mo;
     66     p2:=b.s2*ni[a.s2] mod mo;
     67     exit(p1*p2 mod mo);
     68   end;
     69 
     70 function ask(l,r,x,y,z:longint):longint;
     71   var m:longint;
     72       p,q:int64;
     73   begin
     74     if z>=r then exit(get(tree[x],tree[y]))
     75     else begin
     76       m:=(l+r) shr 1;
     77       if z<=m then exit(ask(l,m,tree[x].l,tree[y].l,z))
     78       else begin
     79         p:=get(tree[tree[x].l],tree[tree[y].l]);
     80         q:=ask(m+1,r,tree[x].r,tree[y].r,z);
     81         exit(p*q mod mo);
     82       end;
     83     end;
     84   end;
     85 
     86 begin
     87   for i:=2 to 1000000 do
     88   begin
     89     if v[i]=0 then
     90     begin
     91       inc(t);
     92       p[t]:=i;
     93       v[i]:=i;
     94     end;
     95     for j:=1 to t do
     96     begin
     97       if i*p[j]>1000000 then break;
     98       v[i*p[j]]:=p[j];
     99       if i mod p[j]=0 then break;
    100     end;
    101   end;
    102   ni[1]:=1;
    103   for i:=2 to mo-1 do
    104   begin
    105     ni[i]:=-int64(mo div i)*ni[mo mod i] mod mo;
    106     if ni[i]<0 then ni[i]:=(ni[i]+mo) mod mo;
    107   end;
    108   readln(n,m);
    109   s[0]:=1;
    110   sd[0]:=1;
    111   for i:=1 to n do
    112   begin
    113     read(a[i]);
    114     s[i]:=s[i-1]*int64(a[i]) mod mo;
    115     sd[i]:=sd[i-1]*int64(ni[a[i]]) mod mo;
    116     x:=a[i];
    117     while x<>1 do
    118     begin
    119       inc(len);
    120       y:=v[x];
    121       e[len].po:=y;
    122       e[len].num:=last[y];
    123       e[len].next:=q[i];
    124       q[i]:=len;
    125       last[y]:=i;
    126       while x mod y=0 do x:=x div y;
    127     end;
    128   end;
    129   t:=0;
    130   tree[0].s1:=1;
    131   tree[0].s2:=1;
    132   h[0]:=build(0,n);
    133   for i:=1 to n do
    134   begin
    135     h[i]:=h[i-1];
    136     j:=q[i];
    137     while j<>0 do
    138     begin
    139       y:=e[j].po;
    140       h[i]:=add(0,n,h[i],e[j].num,y);
    141       j:=e[j].next;
    142     end;
    143   end;
    144   for i:=1 to m do
    145   begin
    146     readln(x,y);
    147     x:=x xor ans;
    148     y:=y xor ans;
    149     if x>y then
    150     begin
    151       t:=x; x:=y; y:=t;
    152     end;
    153     wh:=ask(0,n,h[x-1],h[y],x-1);
    154     ans:=wh*s[y] mod mo*sd[x-1] mod mo;
    155     if ans<0 then ans:=(ans+mo) mod mo;
    156     writeln(ans);
    157   end;
    158 end.
    View Code
  • 相关阅读:
    python简单学------------python基础、print,input,if判断等
    fread读取大文件以及返回值问题(转载)
    github的使用---git版本控制
    python中split函数的使用
    快递小哥逆袭自传:用了6年时间做到了IT部门主管
    Linux系统默默改变了人类世界的生活方式
    浅谈Linux系统运维工程师必备技能
    Linux运维工程师真实的工作状态到底是怎么样的?
    想要学习Linux技术,先好好的读一本Linux书籍吧
    女生可不可以进入IT行业做Linux运维工程师?
  • 原文地址:https://www.cnblogs.com/phile/p/4668869.html
Copyright © 2011-2022 走看看