您的位置:首页 > 其它

jzoj 模拟赛总结(2017.07.11)

2017-07-12 20:36 169 查看
T1.

Oliver的成绩:

题目大意:

一次考试结束了,Oliver给出自己的语文,数学,英语成绩(位数为M)分别与年级N个人中的语文年级第一,数学年级第一,英语年级第一相差多少,如果Oliver是第一,则输出0。

对于50%的数据,0 < N < 1000, 0 < M < 19.

对于100%的数据,0 < N < 10000, 0 &l
4000
t; M < 30.且都为整数

题解:

看题不用想,字符串读入,然后判断长短,相同就按字典序比较,然后高精度随便搞搞。

O(3N)

var
o,maxa,maxb,maxc,a,b,c,a1,b1,c1:string;
i,j,n,m:longint;

function jian(kk,k:string):string;
var
aa,bb,cc:array [0..32] of longint;
i,j,la,lb,lc:longint;
begin
if length(kk)<length(k) then exit('0');
if (length(kk)=length(k)) and (kk<=k) then exit('0');

fillchar(aa,sizeof(aa),0);
fillchar(bb,sizeof(bb),0);
fillchar(cc,sizeof(cc),0);
la:=length(kk);
lb:=length(k);
for i:=1 to la do aa[i]:=ord(kk[la-i+1])-48;
for i:=1 to lb do bb[i]:=ord(K[lb-i+1])-48;
i:=1;
while i<=la do
begin
if aa[i]<bb[i]
then begin
aa[i]:=aa[i]+10;
aa[i+1]:=aa[i+1]-1;
end;
cc[i]:=aa[i]-bb[i];
inc(i);
end;
while cc[i]=0 do dec(i);
jian:='';
for j:=i downto 1 do
jian:=jian+chr(cc[j]+48);
end;

begin
assign(input,'score.in'); reset(input);
assign(output,'score.out'); rewrite(output);
readln(a);
readln(b);
readln(c);
readln(n);
for i:=1 to n do
begin
readln(a1);
readln(b1);
readln(c1);
o:=jian(a1,a);
if (length(o)>length(maxa)) or
((length(o)=length(maxa)) and (o>maxa))
then maxa:=o;

o:=jian(b1,b);
if (length(o)>length(maxb)) or
((length(o)=length(maxb)) and (o>maxb))
then maxb:=o;

o:=jian(c1,c);
if (length(o)>length(maxc)) or
((length(o)=length(maxc)) and (o>maxc))
then maxc:=o;
end;
writeln(maxa,' ',maxb,' ',maxc);
close(input); close(output);
end.


T2.

技能树:

题目大意:

一颗技能树上的每个结点都是一个技能,只有学会了某一项技能以后,才能继续学习它的后继技能。给出n种技能,以及每个技能的前提要求技能,空则表示该技能不需要前提,还有一个L表示技能的最高等级,给出1~L个技能点需求,表示i-1级升到第i级所需要的技能点数(0级表示没有学习过),还有1~L个增幅效果,表示从第I-1级升级到第I级的效果评分。最后给出角色当前习得的技能级别,求分配P技能点数的方案,使得分数总和最高。数据保证不出现非法情况。

1<=n<=20

1<=L<=20

技能点数P<=20

题解:

树形DP+模拟:

等我随便搞搞,很快A,相信我

T3.

团队背包:

题目大意:

M个人都准备了一个背包,用来装旅行用的物品,有N个物品,价值为wi

他们的背包有两个特点:

1. 每个人的背包能装无限多的物品,每种物品有一个价值,但只能装一件;

2. 每个人都很有个性,所以每个人的背包不会完全相同。

求背包价值和最大是多少呢?

【数据规模】

30%的数据 1<=M,N<=15。

60%的数据 1<=M<=200,1<=N<=100。

100%的数据 1<=M<=1,000,000,1<=N<=500,0 < wi<=50。

输出请注意使用64 位整数(Pascal 中的Int64,C++中的long long)。

题解:

DP:

f[i,j]表示前i个物品装j价值物品的方案总数。

然后推出状态转移方程:

f[i,j]:=f[i-1,a[i]]+f[i-1,j-a[i]]

然后如果觉得内存不够优美可以学我滚动滚动,不过第二重循环必须要注意倒推!!

然后从大到小枚举j价值的物品的方案是否出现,出现就用掉,知道用的M个背包都没了。

时间复杂度:O(NΣw[i])

var
f:Array [0..25001] of int64;
a:array [0..501] of longint;
i,j,n,m,x,sum:longint;
ans:int64;
begin
assign(input,'team.in'); reset(input);
assign(output,'team.out');rewrite(output);
readln(m,n);
for i:=1 to n do
begin
read(a[i]);
sum:=sum+a[i];
end;
f[0]:=1;
for i:=1 to n do
begin
for j:=sum downto 0 do
if j>=a[i] then f[j]:=f[j]+f[j-a[i]];

end;
for i:=sum downto 0 do
if m>=f[i]
then begin
m:=m-f[i];
ans:=ans+f[i]*i;
end
else begin
ans:=ans+m*i;
break;
end;
writeln(ans);
close(input); close(output);
end.


T4.

神奇的项链:

从前有一条神奇的项链,为什么说它神奇呢?因为它有两个性质:

1. 神奇的项链可以拉成一条线,线上依次是N 个珠子,每个珠子有一个能量值Ei;

2. 除了第一个和最后一个珠子,其他珠子都满足Ei=(Ei-1+Ei+1)/2+Di。

由于这条项链很长,我们只能知道其两端珠子e[1],e
的能量值。并且我们知道每个珠子的Di是多少。请聪明的你求出这N 个珠子的能量值分别是多少。

任意珠子满足(Ei-1+Ei+1) Mod 2=0

40%的数据 1 < N<=100。

70%的数据 1 < N<=5,000,所有数据(包括计算中的)不超过10^9。

100%的数据 1 < N<=500,000,|E1|、|EN|<=10^14,|Di|<=10^4。

题解:

时间复杂度很明显是O(N)做法,然后看数据要开Int64 / long long

根据e[i]=e[i-1]+e[i+1]/2 +d[i]

我们可以推理

e[i]=e[i-1]/2+e[i+1]/2+d[i]

2e[i]=e[i-1]+e[i+1]+2d[i]

e[i+1]=2e[i]-e[i-1]-2d[i]

然后因为任意位置皆满足此公式,SO

i前移

e[i]=2e[i-1]-e[i-2]-2d[i-1]

因为i-1,i-2的关系,所以要保证i>=3,所以我们先假设e[2]=x

然后推出后面的关系

怎么假设未知数呢?

相信很多人不明白,我一开始也挺困惑,不过,我发现!

设e[i]=sum[i]*X+p[i]

p[i]表示从前面推到第i个珠子能累加到的无未知数X的整数值。

sum[i]表示从前面推到第i个珠子有多少个X,即当前X的系数。

然后最后推到e

就可以发现

e[2]=X=(e
-p
)/sum

然后推一遍

时间复杂度:O(N)

var
sum,e,p,d:Array [0..500001] of int64;
i,j,n,m:longint;

begin
assign(input,'fett.in'); reset(input);
assign(output,'fett.out'); rewrite(output);
read(n); read(e[1],e
); readln;
for i:=2 to n-1 do read(d[i]); readln;
sum[2]:=1; p[1]:=e[1]; p[2]:=0;
for i:=3 to n do
begin
sum[i]:=sum[i-1]*2-sum[i-2];
p[i]:=-p[i-2]+2*p[i-1]-2*d[i-1];
end;
write(e[1]);
e[2]:=(e
-p
) div sum
;
write(' ',e[2]);
for i:=3 to n do
begin
e[i]:=2*e[i-1]-e[i-2]-2*d[i-1];
write(' ',e[i]);
end;
close(input); close(output);
end.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: