jzoj 2017.10.05 模拟赛

来源:互联网 发布:添加windows凭据 编辑:程序博客网 时间:2024/05/20 18:00

T1:
【2012.02.25普及组】探索的奶牛:

题目大意:
农场里有N只奶牛,当碰到路口时,可能会分成两部分(不能为空),每一部分都继续前进,当碰到另一个路口时,再分成两部分,如此反复下去。。。
计算最终被分成多少支队伍,要求任意2部分的差为K。

例:
有6只奶牛,分裂时两个小组的人数差为2.
输出说明: 最终有3支队伍分别为(数量分别为2,1,3)

   6  / \ 2   4    /  \   1    3

1<=N<=1,000,000,000

题解:
这题其实就是一个递归搞定
注意一下情况:
①不能分成2部分就返回0
②能分成2部分但差不为K就返回1(它本身)
③能分成2部分且差为K,递归过去
④考虑有部分<=0的情况
然后如果最后什么都不能分就输出1,否则就输出递归结果,因为对于N,K为3 3,那么就是第一种情况,就是0,那么我们要输出的是1,注意!

var    n,m,k:longint;function dfs(dep:longint):longint;var    i,j,k:longint;begin    dfs:=0;    i:=dep div 2-m div 2;    j:=(dep+1) div 2+m div 2;    if (j-i=m) and (i+j=dep) then    begin       k:=0;       if i>0 then       begin         if (i>=m+2)              then dfs:=dfs+dfs(i)              else dfs:=dfs+1;       end;       if j>0 then       begin         if (j>=m+2)              then dfs:=dfs+dfs(j)              else dfs:=dfs+1;       end;    end else if i+j=dep then dfs:=1;    exit(dfs);end;begin    readln(n,m);    k:=dfs(n);    if k=0 then writeln(1)           else writeln(k);end.

T2:
【2012.02.25普及组】单词:
题目大意:
从前有N只奶牛,他们想知道自己名字的好听度,每个名字都是一个字符串ai。
一个好名字的集合,数量为M,奶牛的名字中每包含一个好名字(“包含”不一定要求连续),那么它的好听度就加1。
请你帮FJ计算每个奶牛名字的好听度。

名字为长度不超过1000的英文字母组成
1<=N<=1000,1<=M<=100
好名字的长度不超过30
所有的名字都不区分大小写

题解:
这题我们直接去枚举:
i枚举好名字,j枚举牛,k枚举名字的字符,找到就累加给f[j]即可
时间复杂度:O(M*∑length(ai))

var    a:array [0..1001] of ansistring;    f:array [0..1001] of longint;    i,j,k,l,n,m:longint;    x:string;begin    readln(n,m);    for i:=1 to n do      begin           readln(a[i]);           a[i]:=lowercase(a[i]);      end;    for i:=1 to m do      begin            readln(x);            x:=lowercase(x);            for j:=1 to n do              begin                   k:=1;                   l:=0;                   while l<length(a[j]) do                   begin                        inc(l);                        if a[j][l]=x[k] then inc(k);                        if k>length(x) then break;                   end;                   if k>length(x) then inc(f[j]);              end;      end;    for i:=1 to n do writeln(f[i]);end.

T3:
【2012.02.25普及组】牛车:
题目大意:
有N 头牛准备在高速公路上赛车,第i个赛车的车速为S[i] 千米/小时,高速公路上一共有M个赛车道。
同车道前面有X个赛车,这辆赛车的车速就会降低D*X千米/小时,当然不会降到0以下,所以车速应该max(S[i]-D*X, 0)。
由于车距很大,所以即使后面的车比前面的车快,你也不用担心会发生碰撞。
高速公路上有一个最低限速L,凡是低于该速度的车不允许在高速上行驶的(注意:减速后的速度若低于L也不能在高速上行驶),现在请你来计算一共可以多少辆赛车在高速公路上行驶。

30%的数据:N≤20,M=1;
60%的数据:N≤1000,M≤10;
100%的数据:1≤N≤50000,1≤M≤100,1≤S[i], L≤10^6,0≤D≤5000。
编号为1..N

题解:
这题我们就先对车的速度从小到大;
因为排序保证了结果的最优,所以枚举一个车速s[i],一个赛道,能放就放,不能就新开一条车道,车道满了或者每个车道都低于限速就走。
时间复杂度:O(N log2 N+N)

var    a:array [0..50001] of longint;    sum:array [0..101] of longint;    ans,n,m,d,l,i,j,k:longint;procedure qsort(l,r:longint);var    i,j,mid:longint;begin    if l>=r then exit;    i:=l; j:=r;    mid:=a[(l+r) div 2];    repeat         while a[i]<mid do inc(i);         while a[j]>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;    qsort(i,r);    qsort(l,j);end;begin    readln(n,m,d,l);    for i:=1 to n do      readln(a[i]);    qsort(1,n);    sum[0]:=0;    for i:=1 to n do      begin            j:=0;            while j<sum[0] do            begin                 inc(j);                 if a[i]-d*sum[j]>=l then break;            end;            if (a[i]-d*sum[j]>=l) and (j<>0)               then inc(sum[j])               else if (sum[0]+1<=m) and (a[i]>=l) then                    begin                         inc(sum[0]);                         sum[sum[0]]:=1;                    end;      end;    for i:=1 to sum[0] do      ans:=ans+sum[i];    writeln(ans);end.

T4:
【2012.02.25普及组】危险系数:
题目大意:
在一条船上,海上有N个岛,编号为1..N,现在他的任务是按照一个给定访问次序A_1,A_2,….A_M去探索这M个岛屿,已经知道任意两个岛屿之间的危险系数,让你找出一个探索序列,只需满足你的探索序列包含给定的A_1..A_M这个序列就可以(不一定要连续),使得总的危险系数最小。

1<=N<=100
2<=M<=10,000

题解:
这题我们不难发现,对于一个
数列a1 a2 a3 a4
要满足这个序列为子序列
就是在这个基础上瞎搞~~
即 a1 b1 b2 a2 b3 a3 b4 b5 a4诸如此类
所以我们要找的最小值
就是a1到a2的最短路,a2到a3的最短路,a3到a4的最短路,a5到……的总和

所以就很容易做了,
一个floyd然后直接求和

时间复杂度:O(N^3+M)

var     f:array [0..101,0..101] of longint;     c:array [0..10001] of longint;     ans,i,j,k,n,m:longint;function min(aa,bb:longint):longint;begin     if aa>bb then exit(bb);     exit(aa);end;begin     readln(n,m);     for i:=1 to m do readln(c[i]);     for i:=1 to n do     begin         for j:=1 to n do read(f[i,j]);         readln;     end;     for k:=1 to n do       for i:=1 to n do         for j:=1 to n do          if (i<>j) and (i<>k) and (j<>k) then             f[i,j]:=min(f[i,j],f[i,k]+f[k,j]);     ans:=0;     for i:=1 to m-1 do       ans:=ans+f[c[i],c[i+1]];     writeln(ans);end.
原创粉丝点击