第一题:
题目描述:
https://61.142.113.109/senior/#main/show/2544
2544. 【NOIP2011模拟9.3】作弊的发牌者 (StandardIO)
贝茜正在与她的N-1(2<= N <= 100)个朋友打牌。她们玩的牌一副为K(N<=K<=100,000,K 为N 的倍数)张。所有牌中,一共有M(M = K/N)张“好牌”,其余的K-M 张为“差牌”。贝茜是游戏的发牌者,很自然地,她想把所有好牌都留给自己。她热衷于
获胜,即使为此必须采取一些不正当的手段。
在若干局游戏后,贝茜的朋友们开始怀疑贝茜在游戏中作弊,于是她们想了个对策:使用新的发牌规则。规则具体如下:
1. 贝茜把牌堆的最上面一张发给她右边的奶牛;
2. 每当贝茜发完一张牌,她都得将牌堆顶部接下来的P(1 <= P<= 10)张牌放到底部去(一般把这个操作称为切牌);
3. 然后,贝茜对逆时针方向的下一头奶牛重复上述的操作;
贝茜绝望地认为,她再也不可能获胜了,于是她找到了你,希望你告诉她,将好牌放在初始牌堆的哪些位置,能够确保它们在发完牌后全集中到她手里。顺带说明一下,我们把牌堆顶的牌定义为1 号牌,从上往下第二张定义为2号牌,依此类推。
Input
第1 行: 3 个用空格隔开的整数:N、K,以及P
Output
贝茜和她的某两个朋友在打一副总共是9 张的牌。她每发出一张牌后,都得在牌堆顶部取出两张放到堆底。
Sample Input
3 9 2
Sample Output
3
7
8
【数据范围】
对于30%的数据,2 <= N <=4,N<=K<= 100
对于100%的数据,2 <= N <=100,N<=K<= 100,000
模拟暴力加点优化就可以了吧,考试时调试了我半天,结果还是被坑了3个点注意细节啊!
参考程序:
var n,k,p,i,j,t,lenb,kk,q,l:longint;
a,b,a2:array[0..1000000]of longint;
procedure kuaipai(l,r:longint);
var i,j,mid,t:longint;
begin
i:=l;j:=r;
mid:=b[(l+r)div 2];
repeat
while b[i]<mid do inc(i);
while b[j]>mid do dec(j);
if i<=j then
begin
t:=b[i];
b[i]:=b[j];
b[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if l<j then kuaipai(l,j);
if i<r then kuaipai(i,r)
end;
begin
readln(n,k,p);
lenb:=0;
for i:=1 to k do a[i]:=i;
kk:=k;
while lenb<k div n do
begin
i:=1;
while i<=kk do
begin
inc(t);
if t mod n=0 then
begin
inc(lenb);
b[lenb]:=a[i];
t:=0;
end;
a[i]:=0;
i:=i+p+1;
end;
if lenb=k div n then break;
i:=i-p-1;
l:=p-(kk-i);
if l>0 then
begin
q:=0;
for i:=1 to kk+10000 do
begin
if a[i]>0 then
begin
inc(q);
a[kk+q]:=a[i];
a[i]:=0;
end;
if q=l thenbreak;
end;
kk:=kk+q;
end;
fillchar(a2,sizeof(a2),0);
for i:=1 to kk do
begin
if a[i]>0 then
begin
inc(a2[0]);
a2[a2[0]]:=a[i];
end;
end;
kk:=a2[0];
a:=a2;
end;
lenb:=k div n;
kuaipai(1,lenb);
for i:=1 to lenb do writeln(b[i]);
end.
第二题:
题目描述:
https://61.142.113.109/senior/#main/show/2545
2545. 【NOIP2011模拟9.3】跳舞 (StandardIO)
小明今天得到一个跳舞毯游戏程序Dance。游戏每次连续出N 个移动的“箭头”,箭头依次标号为1 到N,并且的相应的分数S[1..N]。如果你能“踏中”第i 号箭头,你将获得相应的分数S[i];否则将被扣除相应的分数。
另外,游戏还有一个累计奖励机制:如果踏准次数累计达到T,并且是在踏中第i个箭头达到的,则将得到B[i]的奖励分数,累计也将清零,重新开始。
例如:N=6,T=3,相应的S 和B 分别为{1,2,3,4,5,6}、{0,0,4,7,9,10},如果小明踏中所有箭头,则得分为:(1+2+3+4)+(4+5+6+10)=35
小明是个Dance 高手,可以踏中他想踏中的任意一个箭头。但他发现,根据给定的N,T,S,B,踏中所有的箭头不一定能得最高分,小明很想知道最高能得多少分,你能帮助小明计算一下最多可得多少分吗?
Input
第一行两个整数N 和T。
第二行N 个整数,为S 的相应分数。
第三行也有N 个整数,为B 的相应分数。
Output
只一个整数,可得到的最高分数。
Sample Input
6 3
1 2 3 4 5 6
1 1 1 20 1 1
Sample Output
39
【数据范围】
对于20%的数据0≤N,T≤100;
对于100%的数据0≤N,T≤5000;
S 和B 各有N 个数,所有分数为[0,10000]之间的整数。
果断DP
for i:=1 to n do
begin
for j:=i downto 1 do
if j mod t=0 then
f[j]:=max(f[j]-s[i],f[j-1]+s[i]+b[i]) else
f[j]:=max(f[j]-s[i],f[j-1]+s[i]);
f[0]:=f[0]-s[i];
end;
其中f[i]表示踏中i个的最大得分
参考程序:
var n,t,i,j:longint;
f:array[0..5000]of longint;
s,b:array[1..5000]of longint;
function max(x,y:longint):longint;
begin
if x>y then exit(x) else exit(y);
end;
begin
readln(n,t);
for i:=1 to n do read(s[i]);
for i:=1 to n do read(b[i]);
for i:=1 to n do
begin
for j:=i downto 1 do
if j mod t=0 then
f[j]:=max(f[j]-s[i],f[j-1]+s[i]+b[i]) else
f[j]:=max(f[j]-s[i],f[j-1]+s[i]);
f[0]:=f[0]-s[i];
end;
for i:=1 to n do f[0]:=max(f[0],f[i]);
writeln(f[0]);
end.
第三题:
题目描述:
https://61.142.113.109/senior/#main/show/2546
2546. 【NOIP2011模拟9.3】遥控车 (StandardIO)
平平带着韵韵来到了游乐园,看到了n 辆漂亮的遥控车,每辆车上都有一个唯一的名字name[i]。韵韵早就迫不及待地想玩名字是s 的遥控车。可是韵韵毕竟还小,她想象的名字可能是一辆车名字的前缀(也就是说能确定一个i,使s 是name[i]的前缀),这时她就能玩第i 辆车;或者是一个无中生有的名字,即s 不是任何一辆车名字的前缀,这时候她什么也不能玩。
你需要完成下面的任务:
1.韵韵想了m 个她想要的名字,请告诉她能玩多少次。
2.由于管理员粗心的操作,导致每辆车的摆放位置都可能出现微小的差错,原来第i辆车现在的位置可能是i-1、i、i+1 中的任意一个(第1 辆车的位置不可能是0,第n辆车的位置不可能是n+1)。请你计算出共有多少种可能的排列。
注:数据保证当s 是name[i]的前缀时,i 是唯一确定的。一辆车可以玩多次。
Input
第一行是2 个正整数n、m。
接下来n 行,每行1 个字符串name[i],表示第i 辆车的名字。接下来m 行,每行1 个字符串s,表示韵韵想要的名字。
Output
第一行输出韵韵能玩的次数。第二行输出共有多少种可能的排列。
Sample Input
4 4
Abcd
DeF
AAa
aBccc
Ab
AA
AbC
aBcc
Sample Output
3
5
【数据规模】
对于题目涉及到的字符串严格区分大小写,且长度小于255。
对于20%的数据n≤10,m≤10;
对于40%的数据n≤1000,m≤1000;
对于100%的数据n≤10000,m≤10000。
参考程序:
var n,m,i,j,ans,bz,k,l,lenb,t:longint;
s:string;
a:array[1..10000]of string;
b,c,d:array[1..10000]of longint;
e:array[1..58,0..1000]of longint;
begin
readln(n,m);
for i:=1 to n do
begin
readln(a[i]);
t:=ord(a[i][1])-64;
inc(e[t,0]);
e[t,e[t,0]]:=i;
end;
for i:=1 to m do
begin
readln(s);
l:=length(s);
t:=ord(s[1])-64;
for j:=1 to e[t,0] do
begin
for k:=1 to l do
ifa[e[t,j]][k]<>s[k] then break;
if a[e[t,j]][k]=s[k] then
begin
inc(ans);
break;
end;
end;
end;
writeln(ans);
lenb:=1;
b[1]:=2;
c[1]:=1;
for i:=3 to n do
begin
fillchar(d,sizeof(d),0);
for j:=1 to lenb do
begin
d[j]:=b[j]+c[j]+d[j];
d[j+1]:=d[j] div 10;
d[j]:=d[j] mod 10;
end;
inc(lenb);
if d[lenb]=0 then dec(lenb);
c:=b;
b:=d;
end;
for i:=lenb downto 1 do write(b[i]);
end.
第四题:
题目描述:
https://61.142.113.109/senior/#main/show/2547
2547. 【NOIP2011模拟9.3】旅行 (StandardIO)
Time Limits: 1000 ms MemoryLimits: 256000 KB Detailed Limits
Description
Z 小镇是一个景色宜人的地方,吸引来自各地的观光客来此旅游观光。Z 小镇附近共有N 个景点(编号为1,2,3,…,N),这些景点被M 条道路连接着,所有道路都是双向的,两个景点之间可能有多条道路。也许是为了保护该地的旅游资源,Z 小镇有个奇怪的规定,就是对于一条给定的公路Ri,任何在该公路上行驶的车辆速度必须为Vi。
速度变化太快使得游客们很不舒服,因此从一个景点前往另一个景点的时候,大家都希望选择行使过程中最大速度和最小速度的比尽可能小的路线,也就是所谓最舒适的路线。
Input
第一行包含两个正整数,N和M。
接下来的M 行每行包含三个正整数:x,y 和v。表示景点x 到景点y 之间有一条双向公路,车辆必须以速度v 在该公路上行驶。
最后一行包含两个正整数s,t,表示想知道从景点s 到景点t 最大最小速度比最小的路径。s 和t 不可能相同。
Output
如果景点s 到景点t 没有路径,输出“IMPOSSIBLE”。否则输出一个数,表示最小的速度比。如果需要,输出一个既约分数。
Sample Input
【样例输入1】
4 2
1 2 1
3 4 2
1 4
【样例输入2】
3 3
1 2 10
1 2 5
2 3 8
1 3
【样例输入3】
3 2
1 2 2
2 3 4
1 3
Sample Output
【样例输出1】
IMPOSSIBLE
【样例输出2】
5/4
【样例输出3】
2
【数据范围】
对于100%的数据,1 < N≤500,1≤x,y≤N,0
这题要用到并查集,不会的可以查看http://blog.youkuaiyun.com/fengyingjie2/article/details/52192573
(这是转载某大神的~)
把边按照权值从小到大排好序之后,先是枚举从哪条边开始往下建图,再枚举现在建图用到了哪条边,则对于当前枚举到的边,判断其最老父亲是否相同,不同的话则把他们相连,再加上路径压缩,当连上第j条边时判断s到t是否能通,能通的话则直接判断答案是否需要更新,并直接Break...
参考代码:
var n,m,s,t,i,j,ans1,ans2,p1,p2:longint;
min:real;
a:array[0..50000,1..3]of longint;
father:array[0..500]of longint;
function gys(n,m:longint):longint;
begin
if n mod m=0 then gys:=m
else gys:=gys(m,n mod m);
end;
procedure kuaipai(l,r:longint);
var i,j,mid:longint;
begin
i:=l;j:=r;
mid:=a[(l+r)div 2,3];
repeat
while a[i,3]<mid do inc(i);
while a[j,3]>mid do dec(j);
if i<=j then
begin
a[0]:=a[i];
a[i]:=a[j];
a[j]:=a[0];
inc(i);
dec(j);
end;
until i>j;
if l<j then kuaipai(l,j);
if i<r then kuaipai(i,r)
end;
function getfather(x:longint):longint;
begin
if father[x]=0 then exit(x);
father[x]:=getfather(father[x]);
exit(father[x]);
end;
procedure bingchaji(x,y:longint);
var fx,fy:longint;
begin
fx:=getfather(x);
fy:=getfather(y);
if fx<>fy then
father[fx]:=fy;
end;
begin
readln(n,m);
for i:=1 to m do
readln(a[i,1],a[i,2],a[i,3]);
readln(s,t);
kuaipai(1,m);
min:=maxlongint;
for j:=1 to m do
begin
p1:=-maxlongint;
p2:=maxlongint;
fillchar(father,sizeof(father),0);
for i:=j to m do
begin
if a[i,3]>p1 then p1:=a[i,3];
if a[i,3]<p2 thenp2:=a[i,3];
if getfather(a[i,1])<>getfather(a[i,2])then
begin
bingchaji(a[i,1],a[i,2]);
end;
ifgetfather(s)=getfather(t) then
if min>p1/p2then
begin
min:=p1/p2;
ans1:=p1;
ans2:=p2;
break;
end;
end;
end;
if (ans1=0)and(ans2=0)then
begin
writeln('IMPOSSIBLE');
exit;
end;
if ans1 mod ans2=0 then
begin
writeln(ans1 div ans2);
exit;
end;
t:=gys(ans1,ans2);
ans1:=ans1 div t;
ans2:=ans2 div t;
writeln(ans1,'/',ans2);
end.