A 圆盘自动机
循环矩阵什么的,当时真是没看出规律来。应该把中间过程打出来,说不定就找到规律了。
Codeprogram cell; const FileName='cell'; type matrix=array[1..500] of longint; var a,t,tmp:matrix; b,ans:array[1..500] of int64; n,m,d,k,i,j:longint; temp:Qword; procedure OFile; begin assign(input,FileName+'.in'); assign(output,FileName+'.out'); reset(input);rewrite(output); end; procedure CFile; begin close(input);close(output);end; procedure mul(var a,b,ans:matrix); var i,j:longint; temp:Qword; begin for i:=1 to n do begin temp:=0; for j:=1 to n do temp:=(temp+int64(A[j])*B[(n+i-j)mod n+1])mod m; ans[i]:=temp; end; end; procedure print(var a:matrix); var i,j:longint; begin for i:=1 to n do begin for j:=1 to n do write(a[(n+j-i)mod n+1]:3); writeln;end; end; begin OFile;readln(n,m,d,k); fillchar(A,sizeof(a),0); fillchar(t,sizeof(t),0); for i:=1 to n do begin read(B[i]);B[i]:=B[i] mod m;end; //===init=== T[1]:=1; for i:=1 to d+1 do A[i]:=1; for i:=n downto n-d+1 do A[i]:=1; //===Power=== while k>0 do begin if(k and 1)>0 then begin tmp:=T; mul(tmp,A,T); end; tmp:=A;mul(tmp,tmp,A); k:=k>>1;end; //===slove=== for i:=1 to n do begin temp:=0; for j:=1 to n do temp:=((Qword(T[(n+j-i)mod n+1])*B[j])mod m +temp)mod m; ans[i]:=temp; end; //===print=== for i:=1 to n-1 do write(ans[i],' '); writeln(ans[n]);CFile; end.
B 游戏
先把2D/2D的方程列出来,然后是一个结论((a+b)(c+d)>ac+bd)优化到2D/0D。讲题之前完全想不到啊。第一次接触。这个题目唯一一个难点就在这里。
Codeprogram game; uses math; const FileName='game'; maxl=2000; var f:array[0..maxl,0..maxl] of longint; a,b:array[1..maxl] of longint; i,j,l1,l2:longint; begin filldword(F,sizeof(f)>>2,maxlongint); F[0][0]:=0;readln(L1,L2); for i:=1 to L1 do begin read(A[i]);dec(A[i]);end; for i:=1 to L2 do begin read(B[i]);dec(B[i]);end; for i:=1 to L1 do for j:=1 to L2 do F[i][j]:=min((F[i-1][j-1]),min(F[i-1][j],F[i][j-1])) +A[i]*B[j]; writeln(F[L1][L2]); end.
C 方块(square)
这个题目还是比较有意思,虽然很裸,但是我猜测这种题目是现在NOIp出题的比较可能的方向。之前没怎么写过这种题目,关键还是规律,思路要清晰。整个程序可以说只有这两行:
pos[i]:=max{pos[j]+min(len[i],len[j])}(j=1..i-1)
pos[i]:=pos[i]*sqrt2;
这两行就是题目考察我们的思维能力的地方。还有就是判断是否被遮挡要注意细节,把它投影到X轴上看,还有就是某一块既可以被左边挡住,也坑能呗右边挡住;一个方块既可能被另一个方块挡住,也可能被两个方块挡住。
Codeprogram square; uses math; const Filename='square';maxn=50; var sqrt2,tmp:extended; len:array[1..maxn] of longint; l,r,pos:array[1..maxn] of extended; i,j,n:longint; function cansee(k:integer):boolean; var i:integer; begin cansee:=true; for i:=1 to n do begin if(i<k)and(len[i]>len[k]) then l[k]:=min(max(r[i],l[k]),r[k]); if(i>k)and(len[i]>len[k]) then r[k]:=max(min(l[i],r[k]),l[k]); if abs(l[k]-r[k])<1E-9 then exit(false); end; end; begin Sqrt2:=sqrt(2); while not eof do begin readln(n);for i:=1 to n do read(len[i]); pos[1]:=len[i]/2; for i:=2 to n do begin for j:=1 to i-1 do tmp:=max(pos[j]+min(len[i],len[j]),tmp); pos[i]:=tmp;tmp:=0;end; for i:=1 to n do begin pos[i]:=pos[i]*sqrt2; l[i]:=pos[i]-len[i]/sqrt2; r[i]:=pos[i]+len[i]/sqrt2; end; for i:=1 to n do if cansee(i) then write(i,' '); writeln;end; end.