您的位置:首页 > 其它

2016.07.16【初中部 NOIP提高组 】模拟赛C题解

2016-08-14 07:33 288 查看
题目:https://jzoj.net/senior/#contest/problems/1753

T1:

第一题就是一个数学题目而已,只要懂得∑这个符号的意思,以及有良好的思维即可AC。贴一下最难的一段的就是Yij的:

for i:=1 to n do
begin
for j:=1 to 8 do
begin
ans:=0;
for k:=1 to n do
ans:=ans+abs(sum[k,j]-avg[j]);
if ans=0 then
y[i,j]:=0
else
y[i,j]:=(sum[i,j]-avg[j])/(ans/n);
end;

end;T2:
第二题很明显是二分,二分答案。刚开始看题以为是DP,可以看看n的范围还是算了。二分最短的时间,假设最短时间为x,然后对于每个衣服a[i]-烘干值*x,最后看看x的时间够不够用(自己思考,差不多就是每个div一下的意思),够则缩,反之则扩。注意r的范围尽量弄大一点也没关系,不然可能爆0。

while l<r do
begin
mid:=(l+r) div 2;
if pd(mid) then
begin
r:=mid;
if mid<min then min:=mid;
end
else
l:=mid+1;
end;T3:
第三题考试的时候想到了暴力和二分,可惜二分不会实现。讲完题后我同桌proking也实现了许久。讲题时,一位神犇告诉了我们一个非常厉害的算法。

例如数据是:1,2,3,4,5,我们就把他复制一次,就是1,2,3,4,5,1,2,3,4,5。很明显,最大和为1-5这个序列的和15,注意是原序列。然后我们设一个队列,一旦队列的总和大于15的一半,就开始删掉队头的元素。最后的结果就是每次删完后队列最大的总和。

for i:=1 to 2*n do
begin
inc(len);
s:=s+a[i];
while s>ans div 2 do
begin
dec(len);
dec(s,a[l]);
inc(l);
end;
if s>max then max:=s;
if s=ans div 2 then break;
end;T4:
注意,题目的意思是,选取开头和结尾,期间的数,要大于开头,小于结尾,可以无顺序。据说这道题班上没人想出正解。但是有人想出了O(n^n)水过,数据小没办法。不过还是加了许多优化的。枚举起点,设一个max,表示当前队列中最大(终点)值为多少,往下搜,如果此点>max,则设此点为终点,这样保证了队列终点最大。

for i:=n downto 2 do
begin
min:=a[i];
for j:=i downto 1 do
begin
if a[j]>a[i] then break;
if (a[j]<min)or((j=i)and(a[j]<min)) then
begin
ans:=j;
min:=a[j];
end;

end;
if (i-ans+1>max)and(ans<>0) then max:=i-ans+1;
end;总结:
这次考得很差,该做的题目没做对,主要是数学能力和题目理解能力不太强,今后急需改正
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: