創建時間: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是有權限的是因為不希望有不認識的人。