创建时间:2017/3/13 18:33
镇楼图:
猜猜她是谁~
解题思路:
春节居然也有比赛,一脸萌比完全不知道啊。。其实我本来逛着Bzoj,发现未来日记出新题了——[bzoj4763雪辉],要不shy也来乱搞一下>_<结果不会哦,那就来洛谷一道一道切题。做下来感受是萌比的,对AK的Claris伏身欣赏。
P1:签到题
题意:求Σ(i=l..r)(i-phi(i)),l,r<=10^12,r-l<=10^6。
题解:数n的质因数只能有一个大于sqrt(n),则筛出质数后O(nlnn)对区间[l,r]的各个数分解。
const p=666623333; var L,R,D,Ans:int64; N,i,j,k,tPri:longint; isPri:array[0..1000005]of boolean; Pri:array[0..100005]of longint; Pool,Conv:array[0..1000005]of int64; procedure ct(x,y:longint); begin Pool[x]:=Pool[x]div y*(y-1); while Conv[x]mod y=0 do Conv[x]:=Conv[x]div y end; begin read(L,R); N:=trunc(sqrt(R)); for i:=2 to N do begin if not isPri[i] then begin inc(tPri); Pri[tPri]:=i end; for j:=1 to tPri do begin k:=i*Pri[j]; if k>N then break; isPri[k]:=true; if i mod Pri[j]=0 then break end end; for i:=0 to R-L do begin Pool[i]:=L+i; Conv[i]:=L+i end; for i:=1 to tPri do begin j:=Pri[i]; D:=((L-1)div j+1)*j; while D<=R do begin ct(D-L,j); inc(D,j) end end; for i:=0 to R-L do begin if Conv[i]>1 then Pool[i]:=Pool[i]div Conv[i]*(Conv[i]-1); Ans:=(Ans+i+L-Pool[i])mod P end; write(Ans) end.
P2:美好的每一天
题意:给定小写字母串,询问若干区间的回文子区间个数。
题解:把每个字母想象成一个二进制状态,则该问题即求异或和为二次幂的子区间个数。求前缀和,上莫队。易超时则离散化。
var n,m,t_n,i,j,blo,Ans:longint; c:char; h:array[0..60005]of integer; s,t,u,v,a,b,Res:array[0..60005]of longint; w:array[0..25,0..60005]of longint; procedure sw(var a,b:longint); var c:longint; begin c:=a; a:=b; b:=c end; procedure qs(l,r:longint); var i,j,x,y:longint; begin i:=l; j:=r; x:=b[(l+r)>>1]; y:=v[(l+r)>>1]; repeat while (b[i]<x)or(b[i]=x)and(v[i]<y) do inc(i); while (b[j]>x)or(b[j]=x)and(v[j]>y) do dec(j); if i<=j then begin sw(u[i],u[j]); sw(v[i],v[j]); sw(a[i],a[j]); sw(b[i],b[j]); inc(i); dec(j) end until i>j; if i<r then qs(i,r); if l<j then qs(l,j) end; procedure ds(l,r:longint); var i,j,m:longint; begin i:=l; j:=r; m:=t[(l+r)>>1]; repeat while t[i]<m do inc(i); while t[j]>m do dec(j); if i<=j then begin sw(t[i],t[j]); inc(i); dec(j) end until i>j; if i<r then ds(i,r); if l<j then ds(l,j) end; function ef(x:longint):longint; var l,r,m:longint; begin l:=1; r:=t_n; while l<r do begin m:=(l+r)>>1; if t[m]>=x then r:=m else l:=m+1 end; if x=t[l] then exit(l); exit(0) end; procedure ad(x:longint); var i:longint; begin inc(Ans,h[s[x]]); for i:=0 to 25 do inc(Ans,h[w[i,x]]); inc(h[s[x]]) end; procedure de(x:longint); var i:longint; begin dec(h[s[x]]); for i:=0 to 25 do dec(Ans,h[w[i,x]]); dec(Ans,h[s[x]]) end; begin readln(n,m); for i:=1 to n do begin read(c); s[i]:=s[i-1]xor(1<<(ord(c)-97)); t[i]:=s[i] end; t_n:=n; inc(t_n); t[t_n]:=0; ds(1,t_n); i:=t_n; t_n:=1; for i:=2 to i do if t[i]<>t[i-1] then begin inc(t_n); t[t_n]:=t[i] end; for i:=0 to n do begin for j:=0 to 25 do w[j,i]:=ef(s[i]xor(1<<j)); s[i]:=ef(s[i]) end; blo:=trunc(sqrt(n)); for i:=1 to m do begin read(u[i],v[i]); a[i]:=i; b[i]:=(u[i]-1)div blo end; qs(1,m); h[1]:=1; U[0]:=1; V[0]:=0; for i:=1 to m do begin for j:=V[i-1]+1 to V[i] do ad(j); for j:=V[i-1] downto V[i]+1 do de(j); for j:=U[i-1] to U[i]-1 do de(j-1); for j:=U[i-1]-1 downto U[i] do ad(j-1); Res[a[i]]:=Ans end; for i:=1 to m do writeln(Res[i]) end.
P3:Koishi Loves Construction
题意:构造前缀和、前缀积模n互不相同的序列。
题解:找规律,看题解。
var task,T:longint; procedure main_task1; var n,i:longint; begin read(n); if n=1 then begin writeln('2 1'); exit end; if odd(n) then begin writeln(0); exit end; write(2); for i:=0 to n-1 do if odd(i) then write(' ',i) else write(' ',n-i); writeln end; procedure main_task2; var n,i:longint; function pri(x:longint):boolean; var i:longint; begin for i:=2 to trunc(sqrt(x)) do if x mod i=0 then exit(false); exit(true) end; function pw(x,y:longint):int64; begin if y=0 then exit(1); if y=1 then exit(x); exit(sqr(pw(x,y>>1))mod n*pw(x,y and 1)mod n) end; begin read(n); if n=1 then begin writeln('2 1'); exit end; if n=4 then begin writeln('2 1 3 2 4'); exit end; if not pri(n) then begin writeln(0); exit end; write('2 1'); for i:=2 to n do write(' ',(i*pw(i-1,n-2)+n-1)mod n+1); writeln end; begin read(task,T); for T:=1 to T do if task=1 then main_task1 else main_task2 end.
P4:Koishi Loves Segments
题意:定义线段为一段区间,给定每个点限制覆盖数,求最大覆盖线段数。
题解:从左到右添加线段,不符合时贪心地删掉最远的。超时了?用什么线段树+平衡树,还不用树状数组+堆!
function min(a,b:longint):longint; begin if a>b then exit(b); exit(a) end; procedure sw(var a,b:longint); var c:longint; begin c:=a; a:=b; b:=c end; const oo=$3f3f3f3f; type arr=array[0..800005]of longint; Tree_Arr=object top:longint; f,g:arr; procedure ad(x,y:longint); function sm(x:longint):longint; procedure ct(l,r,x:longint); function sk(l,r:longint):longint; end; Heap=object m:longint; h,id:arr; procedure push(x,y:longint); procedure pop; function top:longint; end; procedure Tree_Arr.ad(x,y:longint); var z:longint; begin z:=x*y; while x<=top do begin inc(f[x],y); inc(g[x],z); inc(x,x and(-x)) end end; function Tree_Arr.sm(x:longint):longint; var t,U,V:longint; begin U:=0; V:=0; t:=x; while t>0 do begin inc(U,f[t]); inc(V,g[t]); dec(t,t and(-t)) end; exit(U*(x+1)-V) end; procedure Tree_Arr.ct(l,r,x:longint); begin ad(l,x); ad(r+1,-x) end; function Tree_Arr.sk(l,r:longint):longint; begin exit(sm(r)-sm(l-1)); end; procedure Heap.push(x,y:longint); begin inc(m); h[m]:=x; id[m]:=y; x:=m; while (x>1)and(h[x]>h[x>>1]) do begin sw( h[x], h[x>>1]); sw(id[x],id[x>>1]); x:=x>>1 end end; procedure Heap.pop; var x,t:longint; begin sw( h[1], h[m]); sw(id[1],id[m]); dec(m); x:=1; while x<<1<=m do begin t:=x<<1; if (t<m)and(h[t+1]>h[t]) then inc(t); if h[t]>h[x] then begin sw(h[x],h[t]); sw(id[x],id[t]); x:=t end else break end end; function Heap.top:longint; begin exit(id[1]) end; var n,m,i,j,t,z,Ans:longint; a,Ls,Rs,P,X,Poi:arr; Ako:Tree_Arr; Yuu:Heap; procedure qs_lr(l,r:longint); var i,j,m:longint; begin i:=l; j:=r; m:=Ls[(l+r)>>1]; repeat while Ls[i]<m do inc(i); while Ls[j]>m do dec(j); if i<=j then begin sw(Ls[i],Ls[j]); sw(Rs[i],Rs[j]); inc(i); dec(j) end until i>j; if i<r then qs_lr(i,r); if l<j then qs_lr(l,j) end; procedure ad(x:longint); begin inc(t); a[t]:=x end; procedure qs_a(l,r:longint); var i,j,m:longint; begin i:=l; j:=r; m:=a[(l+r)>>1]; repeat while a[i]<m do inc(i); while a[j]>m do dec(j); if i<=j then begin sw(a[i],a[j]); inc(i); dec(j) end; until i>j; if i<r then qs_a(i,r); if l<j then qs_a(l,j) end; function ef(x:longint):longint; var l,r,m:longint; begin l:=1; r:=t; while l<r do begin m:=(l+r)>>1; if a[m]>=x then r:=m else l:=m+1 end; exit(l) end; begin read(n,m); for i:=1 to n do begin read(Ls[i],Rs[i]); ad(Ls[i]); ad(Rs[i]); Poi[i]:=n end; for i:=1 to m do begin read(P[i],X[i]); ad(p[i]) end; qs_a(1,t); i:=t; t:=1; for i:=2 to i do if a[i]<>a[i-1] then ad(a[i]); for i:=1 to n do begin Ls[i]:=ef(Ls[i]); Rs[i]:=ef(Rs[i]) end; for i:=1 to m do P[i]:=ef(P[i]); for i:=1 to t do Poi[i]:=oo; for i:=1 to m do Poi[P[i]]:=min(Poi[P[i]],X[i]); Ako.top:=t; qs_lr(1,n); j:=1; for i:=1 to t do begin while (j<=n)and(Ls[j]<=i) do begin Ako.ct(Ls[j],Rs[j],1); Yuu.push(Rs[j],j); inc(j); inc(Ans) end; while Ako.sk(i,i)>Poi[i] do begin z:=Yuu.top; Yuu.pop; Ako.ct(Ls[z],Rs[z],-1); dec(Ans) end end; write(Ans) end.
P5:Koishi Loves Number Theory
题意:f(n)=Σ(i=0..n)x^i,求lcm(f(a1),f(a2),…,f(an))。
题解:①gcd(x^n-1,x^m-1)=x^gcd(n,m)-1.②lcm(a1,a2,…,an)=gcd(奇数个数)/gcd(偶数个数).考虑到gcd个数很少,直接暴力算。
const p=1000000007; type Vector=object n:longint; a:array of int64; procedure clear; procedure push(x:int64); end; Hash=object const p=6662333; var e:longint; head:array[0..P]of longint; next,node,post:Vector; procedure ad(const v,w:int64); function sk(const v:int64):longint; end; procedure Vector.clear; begin n:=0 end; procedure Vector.push(x:int64); begin inc(n); if n>high(a) then setlength(a,n<<1); a[n]:=x end; procedure Hash.ad(const v,w:int64); var u:longint; begin inc(e); u:=v mod p; next.push(head[u]); head[u]:=e; node.push(v); post.push(w) end; function Hash.sk(const v:int64):longint; var i:longint; begin i:=head[v mod p]; while i<>0 do begin if node.a[i]=v then exit(post.a[i]); i:=next.a[i] end; exit(-1) end; var x,Ans,t,s:int64; N,i,j,k:longint; a:array[0..105]of int64; q,s0,s1,tmp,tmp_s0,tmp_s1:Vector; h:Hash; function pw(const x,y:int64):int64; begin if y=0 then exit(1); if y=1 then exit(x); exit(sqr(pw(x,y>>1))mod p*pw(x,y and 1)mod p) end; function ct(const y:int64):int64; begin exit(pw(x,y)-1) end; function iv(const x:int64):int64; begin exit(pw(x,p-2)) end; function gcd(const a,b:int64):int64; begin if b=0 then exit(a); exit(gcd(b,a mod b)) end; begin read(x,N); x:=x mod p; for i:=1 to n do begin read(a[i]); inc(a[i]) end; for i:=1 to n do begin tmp.clear; tmp_s0.clear; tmp_s1.clear; tmp.push(a[i]); tmp_s0.push(1); tmp_s1.push(0); for j:=1 to q.n do begin tmp.push(gcd(a[i],q.a[j])); tmp_s0.push(s0.a[j]); tmp_s1.push(s1.a[j]) end; for j:=1 to tmp.n do begin k:=h.sk(tmp.a[j]); if k=-1 then begin q.push(tmp.a[j]); s0.push(tmp_s1.a[j]); s1.push(tmp_s0.a[j]); h.ad(tmp.a[j],q.n) end else begin s0.a[k]:=(s0.a[k]+tmp_s1.a[j])mod p; s1.a[k]:=(s1.a[k]+tmp_s0.a[j])mod p end end; end; Ans:=iv(x-1); for i:=1 to q.n do Ans:=Ans*pw(ct(q.a[i]),(s1.a[i]-s0.a[i]+p-1)mod(p-1))mod p; Ans:=(Ans+p)mod p; write(Ans) end.
P6:随机数生成器
题意:对一个范围[1,x]的随机整数序列,问若干【区间最小值】的最大值的期望。
题解:E(x)=Σ(s=1..x)(=s的概率)*s=Σ(s=1..x)P(x>=s)。然后就dp。具体可以看原题解。
const p=666623333; var n,x,ix,q,i,m,ll,rr,t,s:longint; Ans:int64; _l,_r,ls,rs:array[0..2005]of longint; _pw,f:array[0..2005]of int64; procedure sw(var a,b:longint); var c:longint; begin c:=a; a:=b; b:=c end; procedure qs(l,r:longint); var i,j,x,y:longint; begin i:=l; j:=r; x:=_l[(l+r)>>1]; y:=_r[(l+r)>>1]; repeat while (_l[i]<x)or(_l[i]=x)and(_r[i]<y) do inc(i); while (_l[j]>x)or(_l[j]=x)and(_r[j]>y) do dec(j); if i<=j then begin sw(_l[i],_l[j]); sw(_r[i],_r[j]); inc(i); dec(j) end until i>j; if i<r then qs(i,r); if l<j then qs(l,j) end; function pw(const x,y:int64):int64; begin if y=0 then exit(1); if y=1 then exit(x); exit(sqr(pw(x,y>>1))mod p*pw(x,y and 1)mod p) end; function ct(_p:int64):int64; var i,j,Gabriel:longint; Raphiel:int64; begin _p:=_p*ix mod p; ct:=0; Gabriel:=0; Raphiel:=0; _pw[0]:=1; for i:=1 to t do _pw[i]:=_pw[i-1]*(1-_p)mod p; for i:=1 to t do begin while rs[Gabriel]<ls[i]-1 do begin Raphiel:=(Raphiel-f[Gabriel]*_pw[i-Gabriel-1])mod p; inc(Gabriel) end; f[i]:=Raphiel; { f[i]:=0; for j:=1 to i-1 do if rs[j]>=ls[i]-1 then f[i]:=(f[i]+f[j]*_pw[i-j-1])mod p; } if ls[i]=1 then f[i]:=(f[i]+_pw[i-1])mod p; f[i]:=f[i]*_p mod p; Raphiel:=(Raphiel*(1-_p)+f[i])mod p; if rs[i]=m then ct:=(ct+f[i]*_pw[t-i])mod p end end; begin read(n,x,q); ix:=pw(x,p-2); for i:=1 to q do read(_l[i],_r[i]); qs(1,q); ll:=_l[1]; rr:=_r[1]; m:=1; for i:=2 to q do if _l[i]<>_l[m] then begin while _r[i]<=_r[m] do dec(m); inc(m); _l[m]:=_l[i]; _r[m]:=_r[i] end; t:=1; ls[t]:=1; rs[t]:=1; ll:=1; rr:=1; for i:=_l[1]+1 to _r[m] do begin if i>_r[ll] then inc(ll); if (rr<m)and(i>=_l[rr+1]) then inc(rr); if ll<=rr then begin inc(t); ls[t]:=ll; rs[t]:=rr end end; for s:=1 to x do Ans:=(Ans+1-ct(s-1))mod p; Ans:=(Ans+p)mod p; write(Ans) end.
P7:雪辉【兼bzoj 4763】
题意:求树上【路径并】的不同颜色种数及mex(mex指最小的未出现的自然数)。
题解:取sqrt(n)个点满足其余点转移到这些点不超过sqrt(n),预处理虚树上任意点对间颜色信息,暴力压位。
program Mirai_Nikki; const MxDword=65535; type Table=object e:longint; head:array[0..100005]of longint; next,node:array[0..200005]of longint; procedure ad(u,v:longint); end; procedure Table.ad(u,v:longint); begin inc(e); next[e]:=head[u]; head[u]:=e; node[e]:=v end; var n,m,Dues,i,j,u,v,tim,blo,blonum,a,Knd,Mex,LastAns:longint; MxQword:qword; Sz:array[0..65536]of longint; c,d,fa,dfn,iskey:array[0..100005]of longint; key,key_fa:array[0..355]of longint; h:array[0..200005]of longint; z:array[0..17,0..200005]of longint; Tr:Table; type Bit=object a:array[0..470]of qword; procedure clear; procedure pt(x:longint); function siz(const x:qword):longint; function knd:longint; function mex:longint; end; procedure Bit.clear; begin fillchar(a,sizeof(a),0) end; procedure Bit.pt(x:longint); begin a[x>>6]:=a[x>>6]or(qword(1)<<(x and 63)) end; function Bit.siz(const x:qword):longint; begin exit(sz[x and MxDword]+sz[(x>>16)and MxDword]+sz[(x>>32)and MxDword]+sz[x>>48]) end; function Bit.knd:longint; var i:longint; begin knd:=0; for i:=0 to 469 do inc(knd,siz(a[i])) end; function Bit.mex:longint; var i,j:longint; begin for i:=0 to 469 do if a[i]<>MxQword then for j:=0 to 63 do if a[i]or(qword(1)<<j)<>a[i] then exit(i<<6+j) end; operator or(const a,b:Bit)c:Bit; var i:longint; begin for i:=0 to 469 do c.a[i]:=a.a[i]or b.a[i] end; var f:array[0..355,0..355]of Bit; tmp:Bit; pb:^Bit; function max(a,b:longint):longint; begin if a>b then exit(a); exit(b) end; function sk(u:longint):longint; var i,v:longint; begin sk:=0; inc(tim); z[0,tim]:=u; dfn[u]:=tim; i:=Tr.head[u]; while i<>0 do begin v:=Tr.node[i]; if dfn[v]=0 then begin fa[v]:=u; d[v]:=d[u]+1; sk:=max(sk,sk(v)); inc(tim); z[0,tim]:=u end; i:=Tr.next[i] end; if (u=1)or(sk<blo) then exit(sk+1); inc(blonum); key[blonum]:=u; iskey[u]:=blonum; exit(0) end; function lw(x,y:longint):longint; begin if d[x]<d[y] then exit(x); exit(y) end; procedure st; var i,j:longint; begin for i:=2 to tim do h[i]:=h[i>>1]+1; for j:=1 to 17 do for i:=1 to tim-1<<j+1 do z[j,i]:=lw(z[j-1,i],z[j-1,i+1<<(j-1)]) end; procedure sw(var a,b:longint); var c:longint; begin c:=a; a:=b; b:=c end; function lca(u,v:longint):longint; var w:longint; begin u:=dfn[u]; v:=dfn[v]; if u>v then sw(u,v); w:=h[v-u+1]; exit(lw(z[w,u],z[w,v-1<<w+1])) end; procedure qs(l,r:longint); var i,j,m:longint; begin i:=l; j:=r; m:=dfn[key[(l+r)>>1]]; repeat while dfn[key[i]]<m do inc(i); while dfn[key[j]]>m do dec(j); if i<=j then begin sw(key[i],key[j]); sw(iskey[key[i]],iskey[key[j]]); inc(i); dec(j) end until i>j; if i<r then qs(i,r); if l<j then qs(l,j) end; procedure Chor(u,v:longint); var w:longint; procedure up(x:longint); var i,j,o:longint; begin while x<>w do begin i:=iskey[x]; if i<>0 then begin j:=0; o:=i; while (o<>1)and(d[key[key_fa[o]]]>=d[w]) do begin inc(j); o:=key_fa[o] end; if j>0 then begin Tmp:=Tmp or f[i,j]; x:=key[o]; if x=w then exit; end end; Tmp.pt(c[x]); x:=fa[x] end end; begin w:=lca(u,v); up(u); up(v); Tmp.pt(c[w]) end; begin for i:=1 to 65535 do Sz[i]:=Sz[i xor(i and(-i))]+1; MxQword:=1; MxQword:=MxQword<<63; MxQword:=MxQword-1+MxQword; read(n,m,Dues); for i:=1 to n do read(c[i]); for i:=2 to n do begin read(u,v); Tr.ad(u,v); Tr.ad(v,u) end; blo:=trunc(sqrt(n))+1; blonum:=1; key[1]:=1; iskey[1]:=1; sk(1); st; qs(1,blonum); for i:=2 to blonum do for j:=i-1 downto 1 do if lca(key[i],key[j])=key[j] then begin key_fa[i]:=j; break end; for i:=2 to blonum do if key_fa[i]<>0 then begin pb:=@f[i,1]; u:=key[i]; v:=key[key_fa[i]]; while u<>v do begin pb^.pt(c[u]); u:=fa[u] end; pb^.pt(c[u]); j:=1; v:=key_fa[i]; while key_fa[v]<>0 do begin inc(j); f[i,j]:=f[i,j-1]or f[v,1]; v:=key_fa[v] end end; Knd:=0; Mex:=0; LastAns:=0; for i:=1 to m do begin tmp.Clear; read(a); for a:=1 to a do begin read(u,v); if Dues=1 then begin u:=u xor LastAns; v:=v xor LastAns end; Chor(u,v) end; Knd:=Tmp.knd; Mex:=Tmp.mex; writeln(Knd,' ',Mex); LastAns:=Knd+Mex end end.
一开始以为雪辉是道树上莫队题,就从零开始去做了bzoj1086[王室联邦]和bzoj4129[Haruna’s Breakfast]。。但回头想想他是强制在线的哦,能用莫队过的强在线也就bzoj3460[Jc的宿舍]了=_=。
其他要说的么,我发现我越来越懒了,题解都写得这么简短了!>ω<
最近深受面向对象编程的毒害!代码真是越来越不可读了。
此外,源代码为了能不损格式地发到qq空间上,我先前写了一个CodeEdit.pas,能生成一些风格的Pascal代码(暂时支持freepascal、Luogu、UOJ风格)。过了好久终于又更qq日志了。
这次是qq日志和博客联动发表(不要问为什么会有镇楼图这种东西,因为这是几年来qq日志的习惯)。qq是有权限的是因为不希望有不认识的人。