T1:
桐桐的雷达:
测试雷达都有一个最高限速和一个最低限速。行驶速度超过最高限速B或低于最低限速A,都认为是违规的。
为了检测探测器是否正常工作,假设多数驾驶员是遵守交通规则的,因此如果有超过10%的数据是违规的,则认为探测器可能出了问题。共有C个人,计算合法速度的平均速度。如果你判断出是探测器坏了,则输出0.0。
1≤A≤200, A≤B≤200, 1≤C≤50
题解:
没什么好说的, < min 亦或者 > max 都sum+=1
然后10sum>c就输出0.0
可以就输出平均速度,不过是合法速度的平均而不是全部的平均
时间复杂度:O(C)
var
ans,a,b,c,i,j,x:longint;
begin
assign(input,'radar.in'); reset(input);
assign(output,'radar.out');rewrite(output);
readln(a,b,c);
ans:=0; j:=0;
for i:=1 to c do
begin
read(x);
if (x<a) or (x>b)
then inc(j)
else ans:=ans+x;
end;
if j*10>c
then writeln('0.0')
else writeln(ans/(c-j):0:4);
close(input); close(output);
end.
T2:
桐桐的游戏:
桐桐最近在玩一个跳棋游戏,规则是:有个圆圈,分成N等分,顺时针标号为1到N。假设其中有些段是障碍。桐桐从1号段出发,每次顺时针跳K段,目标是跳到第Z号段,但过程中不能跳到障碍段上去。桐桐想请你帮忙,给出N,Z,以及M个障碍的位置,求出最小的K。
2≤N≤1000, 2≤Z, 0 ≤M≤N-2
题解:
模拟即可
因为答案K 的范围 1≤K≤N,所以可以枚举
对于一个枚举到的i,
从1开始每次跳i步
不过注意,
①跳到障碍物,退出
②跳出死循环,退出
③跳到点Z,退出直接输出
这样时间复杂度是O(N^2)
var
a,b:array [0..1001] of boolean;
i,j,n,m,z,x:longint;
begin
assign(input,'comfort.in'); reset(input);
assign(output,'comfort.out');rewrite(output);
readln(n,z,m);
for i:=1 to m do
begin
read(x);
b[x]:=true;
end;
for i:=1 to n do
begin
for j:=1 to n do a[j]:=false;
j:=1; a[1]:=true;
while not(a[z]) do
begin
j:=j+i;
if j>n then j:=j mod n;
if (b[j]) or (a[j]) then break;
a[j]:=true;
end;
if a[z] then
begin
writeln(i);
close(input); close(output);
halt;
end;
end;
end.
T3;
桐桐偶然发现一个递归函数w(a,b,c)有以下性质:
如果a<=0 or b<=0 or c<=0就返回值1;
如果a>20 or b>20 or c>20就返回w(20,20,20);
如果a < b并且b < c就返回w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
其它别的情况就返回w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1)。
给出a,b,c,求出这个简单的递归函数的值。
-50≤a,b,c≤50
题解:
这题其实很简单,就是一个递归
注意一下
①
a<=0 or b<=0 or c<=0就返回值1
这里照做即可
②
如果a >20 or b>20 or c >20就返回w(20,20,20);
这里可以在递归过程中求出w(20,20,20)然后直接去用这个w(20,20,20)的值,当作一个已知值去做,因为这是可求的,为1048576,就可以省很多这种情况的时间
③
如果a < b并且b < c
返回w(a,b,c-1)+w(a,b-1,c-1)-w(a,b-1,c);
其它别的情况
返回w(a-1,b,c)+w(a-1,b-1,c)+w(a-1,b,c-1)-w(a-1,b-1,c-1)
照做
这种分治题其实就特别容易了,注意一下对其能做的小优化,以及细节即可得分=- =
var
w:array [-51..51,-51..51,-51..51] of longint;
a,b,c,i,j,k:longint;
procedure dfs(x,y,s:longint);
begin
if w[x,y,s]>0 then exit;
if (x<=0) or (y<=0) or (s<=0) then begin w[x,y,s]:=1; exit; end;
if (x>20) or (y>20) or (s>20) then begin w[x,y,s]:=1048576; exit end;
if (x<y) and (y<s) then
begin
dfs(x,y,s-1); dfs(x,y-1,s-1); dfs(x,y-1,s);
w[x,y,s]:=w[x,y,s-1]+w[x,y-1,s-1]-w[x,y-1,s];
end else
begin
dfs(x-1,y,s); dfs(x-1,y-1,s); dfs(x-1,y,s-1); dfs(x-1,y-1,s-1);
w[x,y,s]:=w[x-1,y,s]+w[x-1,y-1,s]+w[x-1,y,s-1]-w[x-1,y-1,s-1];
end;
end;
begin
assign(input,'function.in'); reset(input);
assign(output,'function.out');rewrite(output);
readln(a,b,c);
write('w(',a,', ',b,', ',c,') = ');
dfs(a,b,c);
write(w[a,b,c]);
writeln;
close(input); close(output);
end.
T4;
桐桐的新闻系统:
桐桐设计了一套新闻系统——Argus。
向Argus注册的指令具有以下格式:
Register Q_num Period
Q_num 是用户的ID, Period是间隔。注册后Period 秒,结果会第一次到达。
所有的用户都有不同的 Q_num。桐桐测试了一段时间后,想知道系统前K次发送给谁新闻了。如果同一时间发送多个新闻,以 Q_num 的升序排列。
指令数不超过1000,K<= 10000
0 < Q_num <= 3000
0 < Period <= 3000
题解:
这题一开始我用堆做,结果弄得很长,后来发现数据特别小,所以排序以后暴力枚举一下也可以。
我们先对Q_num进行排序,~~快排这时比不过插排!~
~
然后我们每次在里面找一个最小的时间t[i]输出,
然后将这个ID下一次发送的时间tt[i]求出来,即加上
Qi_Period。
下一次也是这样找最小值
因为Q_num排序了的原因我们可以忽略它的t[]相等的情况,所以程序就特别好写了
时间复杂度:O(n log n+K*指令数)
var
rp:array [0..1001,1..3] of longint;
x,y,i,j,k,l,n:longint;
s,p:ansistring;
procedure qsort(l,r:longint);
var
i,j,mid:longint;
begin
if l>=r then exit;
i:=l; j:=r;
mid:=rp[(l+r) div 2,3];
repeat
while (rp[i,3]<mid) do inc(i);
while (rp[j,3]>mid) do dec(j);
if i<=j then
begin
rp[0]:=rp[i];
rp[i]:=rp[j];
rp[j]:=rp[0];
inc(i); dec(j);
end;
until i>j;
qsort(i,r);
qsort(l,j);
end;
begin
assign(input,'argus.in'); reset(input);
assign(output,'argus.out'); rewrite(output);
readln(s);
n:=0;
while s<>'#' do
begin
j:=pos(' ',s); delete(s,1,j); j:=pos(' ',s);
p:=copy(s,1,j-1); val(p,x);
delete(s,1,j); val(s,y);
inc(n);
rp[n,1]:=y;
rp[n,2]:=y;
rp[n,3]:=x;
readln(s);
end;
qsort(1,n);
readln(k);
for i:=1 to k do
begin
l:=1;
for j:=2 to n do
if (rp[j,1]<rp[l,1]) then l:=j;
writeln(rp[l,3]);
rp[l,1]:=rp[l,1]+rp[l,2];
end;
close(input); close(output);
end.