鄙人在h8oj上玩了幾天,難題是一道也沒有做出來。。。。
大概的總結下,一共有14道:
1.神題A+B problem(代碼最短獎)
/**************************************************************<br /> Problem: 1000<br /> User: ImSB<br /> Language: Pascal<br /> Result: Accepted<br /> Time:0 ms<br /> Memory:244 kb<br />****************************************************************/</p><p>var a,b:byte;begin read(a,b);write(a+b)end.
2.
[BeiJing2006]狼抓兔子
平面圖網路流的最短路最佳化,開始沒有注意雙向邊,固執的WA了3次。
3.
[FJOI2007]輪狀病毒
f[i]=f[i-1]*2+g[i-1];g[i]=f[i-1]+g[i-1];
(f為i這個點所在的聯通塊沒有和根相連,g反之)。
4.
[ZJOI2006]物流運輸
dp,一開始竟然想狀態壓縮去了,慚愧。。。
5.
[HNOI2008]Cards
直接運用XXXX引理,就可以把本文題轉化成為往3個背包中放物體,恰好全部放滿的方案數。
還有一個要說的就是DP的時候是可以最佳化成3維的,狀態為F[I,X,Y]表示已經放了i個物品,其中第一個背包放了x的容量,第二個背包放了y的容量,而第三個背包可以直接由這幾個狀態推過來。
/**************************************************************<br /> Problem: 1004<br /> User: ImSB<br /> Language: Pascal<br /> Result: Accepted<br /> Time:30 ms<br /> Memory:252 kb<br />****************************************************************/</p><p>program h84;<br />var<br /> f:array[-20..20,-20..20] of longint;<br /> a:array[0..60] of longint;<br /> o:array[0..60] of boolean;<br /> n,i,j,t,m,mo,s1,s2,s3,ans:longint;</p><p>procedure work;var i,j,k:longint;<br />begin<br /> fillchar(o,sizeof(o),0);<br /> fillchar(f,sizeof(f),0);<br /> f[0,0]:=1;<br /> for i:=1 to n do<br /> if not o[i] then begin<br /> j:=i;t:=0;<br /> while not o[j] do begin<br /> o[j]:=true;j:=a[j];inc(t);<br /> end;<br /> if t>20 then exit;<br /> for j:=s1 downto 0 do<br /> for k:=s2 downto 0 do<br /> f[j,k]:=(f[j,k]+f[j-t,k]+f[j,k-t]) mod mo;<br /> end;<br /> ans:=(ans+f[s1,s2]) mod mo;<br />end;</p><p>begin<br /> readln(s1,s2,s3,m,mo); n:=s1+s2+s3;<br /> for i:=1 to m do begin<br /> for j:=1 to n do read(a[j]);<br /> work;<br /> end;<br /> for i:=1 to n do a[i]:=i; work;<br /> for i:=1 to mo-2 do ans:=ans*(m+1) mod mo;<br /> writeln(ans);<br />end.
6.
[HNOI2008]神奇的國度
紅果果的弦圖,先求出完美消除序列,然後在利用倒序的完美消除序列貪心即可。
7.
[HNOI2008]水平可見直線
赤裸裸的半平面交。。
8.
[HNOI2008]越獄
ans=m^n-m*(m-1)^(n-1).
9.
[HNOI2008]GT考試
wa了一次,原因是因為轉移的時候理解錯了,無恥的讓我過範例了。
10.
[HNOI2008]明明的煩惱
轉至pouy94
11.
[HNOI2008]玩具裝箱
比較經典的斜率最佳化DP,我個人在推導斜率式子的時候喜歡用半平面交,很無奈的有一次實除,不過很好思考。
/**************************************************************<br /> Problem: 1010<br /> User: ImSB<br /> Language: Pascal<br /> Result: Accepted<br /> Time:250 ms<br /> Memory:2884 kb<br />****************************************************************/</p><p>program h810;<br />type real=extended;<br />var<br /> f,a,b,s,x:array[0..50000] of real;<br /> q:array[0..50000] of longint;<br /> n,i,l,r:longint;<br /> d,aa,bb:real;<br />begin<br /> readln(n,d);d:=d+1;<br /> for i:=1 to n do readln(s[i]);<br /> for i:=1 to n do s[i]:=s[i]+s[i-1];<br /> for i:=1 to n do s[i]:=s[i]+i;<br /> l:=1;r:=1;q[1]:=0;<br /> for i:=1 to n do begin<br /> while (l<r)and(s[i]>x[l+1]) do inc(l);<br /> f[i]:=a[l]*s[i]+b[l]+sqr(s[i]-d);<br /> aa:=-2*s[i];bb:=f[i]+s[i]*s[i]+2*s[i]*d;<br /> while (l<r)and(x[r]*aa+bb<x[r]*a[r]+b[r]) do dec(r);<br /> inc(r);a[r]:=aa;b[r]:=bb;<br /> x[r]:=(b[r]-b[r-1])/(a[r-1]-a[r]+1e-15);<br /> end;<br /> writeln(f[n]:0:0);<br />end.
12.
[Jsoi2011]括弧序列
看到了翻轉,頭腦中的演算法就只剩下splay了,具體操作如下:
考慮一個區間,貪心一般的消除成對的括弧,必然最後剩下的是這樣的玩意:‘)))((((’所以我只要維護有多少個這樣的左括弧和右括弧就可以了。
這道題道題到底是卡pascal還是卡我猥瑣的單旋splay?在網上下了別人比我快很多的程式在本機跑速度沒很大的差別啊。。
速度墊底了,以後也會是。。
/**************************************************************<br /> Problem: 2209<br /> User: ImSB<br /> Language: Pascal<br /> Result: Accepted<br /> Time:17780 ms<br /> Memory:3872 kb<br />****************************************************************/</p><p>program ex1;<br />{$inline+}<br />var<br /> l,r,a,b,s,a1,b1,a2,b2:array[0..100002] of longint;<br /> n,q,i,t,ll,rr,ls,rs,tmp,root,tt:longint;<br />function rd:char;begin read(rd) end;<br />procedure swap(var a,b:longint);inline;begin tmp:=a;a:=b;b:=tmp end;<br />procedure update(i:longint);inline;<br />begin<br /> ls:=l[i];rs:=r[i];<br /> s[i]:=s[ls]+s[rs]+1;<br /> if a[i]=0 then begin<br /> a1[i]:=a1[ls];b1[i]:=b1[ls]+1;<br /> a2[i]:=a2[ls]+ord(b2[ls]=0);<br /> b2[i]:=b2[ls]-ord(b2[ls]>0);<br /> end else begin<br /> a2[i]:=a2[ls];b2[i]:=b2[ls]+1;<br /> a1[i]:=a1[ls]+ord(b1[ls]=0);<br /> b1[i]:=b1[ls]-ord(b1[ls]>0);<br /> end;<br /> if b1[i]>a1[rs] then inc(b1[i],b1[rs]-a1[rs]) else begin<br /> inc(a1[i],a1[rs]-b1[i]);b1[i]:=b1[rs];<br /> end;<br /> if b2[i]>a2[rs] then inc(b2[i],b2[rs]-a2[rs]) else begin<br /> inc(a2[i],a2[rs]-b2[i]);b2[i]:=b2[rs];<br /> end;<br />end;</p><p>procedure left(var i:longint);inline;var j:longint;<br />begin<br /> j:=r[i];r[i]:=l[j];l[j]:=i;<br /> update(i);update(j);i:=j;<br />end;</p><p>procedure right(var i:longint);inline;var j:longint;<br />begin<br /> j:=l[i];l[i]:=r[j];r[j]:=i;<br /> update(i);update(j);i:=j;<br />end;</p><p>procedure put(i,j:longint);inline;<br />begin<br /> if odd(j>>1) then begin<br /> swap(a1[i],a2[i]);swap(b1[i],b2[i]);<br /> a[i]:=1-a[i];b[i]:=b[i] xor 2;<br /> end;<br /> if odd(j>>2) then begin<br /> swap(a1[i],b2[i]);swap(a2[i],b1[i]);<br /> b[i]:=b[i] xor 4;swap(l[i],r[i]);<br /> end;<br />end;</p><p>procedure splay(var i:longint;j:longint);inline;<br />begin<br /> if b[i]<>0 then begin<br /> put(l[i],b[i]);put(r[i],b[i]);<br /> b[i]:=0;<br /> end;<br /> if s[l[i]]>=j then begin<br /> splay(l[i],j);right(i);<br /> end else<br /> if j>s[l[i]]+1 then begin<br /> splay(r[i],j-s[l[i]]-1);left(i);<br /> end;<br />end;</p><p>procedure make(var i:longint;ll,rr:longint);<br />begin<br /> if ll>rr then exit;<br /> i:=(ll+rr)>>1;<br /> make(l[i],ll,i-1);<br /> make(r[i],i+1,rr);<br /> update(i);<br />end;</p><p>begin<br /> readln(n,q);<br /> for i:=2 to n+1 do a[i]:=ord(rd=')');<br /> make(root,1,n+2);<br /> for q:=1 to q do begin<br /> readln(t,ll,rr);<br /> splay(root,ll);<br /> splay(root,rr+2);<br /> i:=r[l[root]];<br /> if t=0 then writeln((a1[i]+b1[i])>>1+a1[i] and 1) else begin<br /> put(i,1<<t);<br /> update(l[root]);<br /> update(root);<br /> end;<br /> end;<br />end.
13.
[SDOI2011]打地鼠
一開始就想到了O(N^4)的演算法,就是枚舉鎚子的大小貪心的N^2的驗證,後來發現因為每次肯定是捶掉鎚子面積大小個地鼠,所以吧所有地鼠總數統計,必然為面積大小的倍數,這樣最壞也只會有O(Log(s)^2)次驗證,然後就讓我過了。。。
N^2的驗證需要一點小技巧,類似與時間點事件的東西。
不知到是不是標準演算法,不過速度還不錯,代碼量也很少。
/**************************************************************<br /> Problem: 2241<br /> User: ImSB<br /> Language: Pascal<br /> Result: Accepted<br /> Time:30 ms<br /> Memory:564 kb<br />****************************************************************/</p><p>program ex2;<br />var<br /> a,b:array[-100..100,-100..100] of longint;<br /> c:array[0..100] of longint;<br /> n,m,i,j,s,ans:longint;</p><p>procedure ck(x,y:longint);var i,j,t:longint;<br />begin<br /> fillchar(c,sizeof(c),0);<br /> for i:=1 to n do begin<br /> t:=0;<br /> for j:=1 to m do begin<br /> dec(t,b[i,j-y]+b[i-x,j]-b[i-x,j-y]);<br /> inc(c[j],t);<br /> b[i,j]:=a[i,j]-c[j];<br /> if b[i,j]<0 then exit;<br /> inc(t,b[i,j]);<br /> inc(c[j],b[i,j]);<br /> end;<br /> end;<br /> ans:=s div (x*y);<br />end;</p><p>begin<br /> readln(n,m);<br /> for i:=1 to n do for j:=1 to m do begin<br /> read(a[i,j]);inc(s,a[i,j]);<br /> end;<br /> ans:=maxlongint;<br /> for i:=1 to n do if s mod i=0 then<br /> for j:=1 to n do if (s mod (i*j)=0)and(s div (i*j)<ans)<br /> then ck(i,j);<br /> writeln(ans);<br />end.
14.
[ZJOI2007]最大半連通子圖
圖論太弱了,做了道關於tarjan的題目,縮點以後求最長鏈:
/**************************************************************<br /> Problem: 1093<br /> User: cjld<br /> Language: Pascal<br /> Result: Accepted<br /> Time:2640 ms<br /> Memory:12920 kb<br />****************************************************************/</p><p>program ex1;<br />{$inline+}<br />var<br /> d,f,g,z,a,fa,oo:array[0..100000] of longint;<br /> p,next:array[0..1000000] of longint;<br /> o:array[0..100000] of boolean;<br /> t,i,j,k,n,m,mo,t1,t2,t3,ans1,ans2,task:longint;</p><p>procedure dfs(i:longint);inline;var j,k,tt:longint;<br />begin<br /> k:=d[i];j:=p[k];<br /> inc(t);tt:=t;<br /> a[i]:=t;z[t]:=i;o[i]:=true;<br /> while k<>0 do begin<br /> if a[j]=0 then dfs(j);<br /> if o[j]and(a[j]<a[i]) then a[i]:=a[j];<br /> k:=next[k];j:=p[k];<br /> end;<br /> if tt=a[i] then begin<br /> inc(task);<br /> t1:=t-tt+1;g[i]:=1;<br /> for t:=tt to t do begin<br /> fa[z[t]]:=i;<br /> k:=d[z[t]];j:=fa[p[k]];<br /> while k<>0 do begin<br /> if not o[j]and(j<>0)and(oo[j]<>task)then<br /> if f[j]>f[i] then begin<br /> f[i]:=f[j];g[i]:=g[j];<br /> end else if f[j]=f[i] then inc(g[i],g[j]);<br /> oo[j]:=task;k:=next[k];j:=fa[p[k]];<br /> end;<br /> end;<br /> for t:=t downto tt do o[z[t]]:=false;<br /> inc(f[i],t1);<br /> if f[i]>ans1 then begin<br /> ans1:=f[i];ans2:=g[i]<br /> end else if f[i]=ans1 then inc(ans2,g[i]);<br /> dec(t);g[i]:=g[i] mod mo;ans2:=ans2 mod mo;<br /> end;<br />end;</p><p>begin<br /> readln(n,m,mo);<br /> for i:=1 to m do begin<br /> readln(j,k);inc(t);<br /> next[t]:=d[j];d[j]:=t;p[t]:=k;<br /> end;<br /> t:=0;<br /> for i:=1 to n do if a[i]=0 then dfs(i);<br /> writeln(ans1);writeln(ans2);<br />end.