一道防AK的好题
不得不吐槽这个题目背景和算法。这就是一脑筋急转弯啊。
Code program hard; CONST FileName='hard'; var n,i,tot:longint; x,a,b,c,ans:array[1..500000] of int64; left,right:int64; function calc(a,b,c:int64):int64; var i:longint; t:int64; begin for i:=1 to n do begin t:=a*(i+1)*x[i]*x[i]+(b+1)*i*x[i]+c+i; write(t:5); if(t=0)then calc:=i; end; end; BEGIN readln(n); for i:=1 to n do read(x[i]); while not eof do begin inc(tot); readln(a[tot],b[tot],c[tot]); end; ans[tot-1]:=-a[tot]; for i:=tot-1 downto 2 do begin left:=a[i]*(ans[i]+1)*x[ans[i]]*x[ans[i]]+(b[i]+1)*ans[i]*x[ans[i]]+c[i]+ans[i]; right:=(ans[i]+1)*x[ans[i]]*x[ans[i]]+ans[i]*x[ans[i]]+1; ans[i-1]:=-left div right end; for i:=1 to tot-1 do writeln(ans[i]); END.
天空中的繁星
四十分做法得了70分,好开心。
Code CONST dx:array[1..4] of longint=(1,-1,0,0); dy:array[1..4] of longint=(0,0,1,-1); maxn=500; var Q:array[1..maxn*maxn,1..2] of longint; vis,A,map:array[0..maxn+1,0..maxn+1] of boolean; sum:array[0..maxn+1,0..maxn+1] of longint; n,m,p,i,j,k,l,ans:longint; s:ansistring; procedure BFS(x,y:longint); var h,t,i,nx,ny:longint; isstar:boolean; begin h:=0;t:=1; Q[1][1]:=x; Q[1][2]:=y; vis[x][y]:=true; while h<t do begin inc(h);isstar:=true; for i:=1 to 4 do begin nx:=Q[h][1]+dx[i]; ny:=Q[h][2]+dy[i]; if(map[nx][ny])and(not vis[nx][ny]) then begin vis[nx][ny]:=true;inc(t); Q[t][1]:=nx;Q[t][2]:=ny; end else if not map[nx][ny] then isstar:=false; end; if isstar then A[Q[h][1]][Q[h][2]]:=true; end; end; BEGIN readln(n,m,p); for i:=1 to n do begin readln(s); for j:=1 to m do if s[j]='*' then map[i][j]:=true; end; for i:=1 to n do for j:=1 to m do if(not vis[i][j])and(map[i][j]) then BFS(i,j); for i:=1 to n do for j:=1 to m do begin sum[i][j]:=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]; if A[i][j] then inc(sum[i][j]); for k:=1 to i-2 do for l:=1 to j-2 do if sum[i-1][j-1]-sum[i-1][l]- sum[k][j-1]+sum[k][l]>=p then inc(ans); end; writeln(ans); END.
应该注意到,对于给定的上、下、右三个边界,左边界能否满足条件满足一个单调性,是可以二分的,如果继续优化发现右边界增大,最大的满足条件的左边界不会减小,通过左边界计算方案数。滑窗应该算是新知识。
Code program star; CONST dx:array[1..4] of longint=(1,-1,0,0); dy:array[1..4] of longint=(0,0,1,-1); FileName='star'; maxn=500; var Q:array[1..maxn*maxn,1..2] of longint; vis,A,map:array[0..maxn+1,0..maxn+1] of boolean; sum:array[0..maxn+1,0..maxn+1] of longint; n,m,p,i,j,k,r,mid,l:longint; s:ansistring; find:boolean; ans:int64; function calc(a,b,c,d:longint):longint; begin calc:=sum[c][d]-sum[c][b-1]-sum[a-1][d]+sum[a-1][b-1];end; procedure BFS(x,y:longint); var h,t,i,nx,ny:longint; isstar:boolean; begin h:=0;t:=1; Q[1][1]:=x; Q[1][2]:=y; vis[x][y]:=true; while h<t do begin inc(h);isstar:=true; for i:=1 to 4 do begin nx:=Q[h][1]+dx[i]; ny:=Q[h][2]+dy[i]; if(map[nx][ny])and(not vis[nx][ny]) then begin vis[nx][ny]:=true;inc(t); Q[t][1]:=nx;Q[t][2]:=ny; end else if not map[nx][ny] then isstar:=false; end; if isstar then A[Q[h][1]][Q[h][2]]:=true; end; end; BEGIN Assign(input,FileName+'.in'); Assign(output,FileName+'.out'); Reset(input);Rewrite(output); readln(n,m,p); for i:=1 to n do begin readln(s); for j:=1 to m do if s[j]='*' then map[i][j]:=true; end; for i:=1 to n do for j:=1 to m do if(not vis[i][j])and(map[i][j]) then BFS(i,j); for i:=1 to n do for j:=1 to m do begin sum[i][j]:=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]; if A[i][j] then inc(sum[i][j]); l:=1; end; for i:=1 to n do for j:=i+2 to n do begin l:=0;//滑了个窗 for k:=3 to m do begin while calc(i+1,l+2,j-1,k-1)>=p do inc(l); inc(ans,l); end; { 二了个分 for k:=3 to m do begin l:=0;r:=k; while l<r-1 do begin mid:=(l+r)>>1; if calc(i+1,mid+1,j-1,k-1)>=p then l:=mid else r:=mid; end; inc(ans,l); end; } end; writeln(ans); Close(input);Close(output); END.
考试没来得及交,按二十分写的暴力居然过了6个点。
Code //写的乱七八糟。。。 program password; var s,p:array[1..2000] of char; a,b,l,r,maxi,n,ans,ans2,temp,len,i,j:longint; begin readln(n); for i:=1 to n do begin read(s[i]); p[n-i+1]:=s[i]; end; len:=0; for i:=1 to n do begin temp:=0; for j:=1 to n do if(p[j]=s[i+j-1])and(i+j-1<n-j+1) then inc(temp) else break; if temp>len then begin len:=temp; maxi:=i; end; end; ans:=len<<1; l:=maxi+len-1;r:=n-len; for i:=l to r do for j:=i+1 to r do begin len:=(j-i+1);temp:=0; if(len and 1)=1 then begin a:=i-1+(len+1)>>1-1; b:=a+2; temp:=1; end else begin a:=i+-1+len>>1; b:=i+-1+a+1; end; while(l<=a)and(b<=r)and(s[a]=s[b])do begin inc(temp,2); dec(a);inc(b); end; if temp>ans2 then ans2:=temp; end; inc(ans,ans2); writeln(ans); end.
全部拿暴力分,排到51名,显然发现第一题是个脑筋急转弯的人不多。手快点就好了,第三题交上就能rank24了,要坚定敢于写暴力的信心~~~~~