jzoj C组 2017.1.15比赛

第一题

题目描述

小x有一个由n个整数组成的数列。他现在可以任意交换数列中两个相邻的元素。小x想知道,能否通过一些操作,使得任意两个相邻的元素不同。

输入

第一行一个整数t,表示测试数据的组数。

每组数据第一行包含一个整数n,表示数列中元素的个数。第二行包含n个整数a1,a2,…,an,表示数列中元素的初始状态。

输出

输出t行,对于第i组测试数据,如果小x能够得到他所想要的序列,输出“YES”,否则输出“NO”(不包含引号)。

样例输入

3

1

1

3

1 1 2

4

7 7 7 7

样例输出

YES

YES

NO

数据范围限制

【数据范围】

对于100%的数据:1<=t<=100,1<=n<=100,1<=ai<=1000。


找到每种元素的个数,如果这个元素的个数大于(n+1) div 2就输出NO,否则输出YES


代码如下:

var  bool:boolean;
     t,i,j,n,k,max,min:longint;
     a:array[1..1000]of longint;

begin
  assign(input,'permutation.in');
  assign(output,'permutation.out');
  reset(input);
  rewrite(output);
  readln(t);
  for k:=1 to t do
    begin
      fillchar(a,sizeof(a),#0);
      readln(n);
      min:=1001;
      for i:=1 to n do
        begin
          read(j);
          inc(a[j]);
          if j>max then max:=j;
          if j<min then min:=j;
        end;
      bool:=false;
      for i:=min to max do
        begin
          if a[i]>(n+1)div 2 then
            begin
              bool:=true;
              break;
            end;
        end;
      if bool then writeln('NO')
             else writeln('YES');
    end;
  close(input);
  close(output);
end.

第二题

题目描述

这里写图片描述

输入

第一行两个用空格分开的整数n和m,分别表示P(x)和Q(x)的最高项指数。

第二行包含n+1用空格分开的整数,a0,a1,…,an,表示P(x)的每项系数。

第三行包含m+1用空格分开的整数,b0,b1,…,bm,表示Q(x)的每项系数。

输出

如果最后得到的极限为正无穷,输出“Infinity”;

如果为负无穷,输出“-Infinity”;

如果最后得到的极限为0,输出“0/1”;

否则,输出一个最简分数,为所得极限的值,以“p/q”的形式,p为分子,q为分母。

样例输入

limit.in1:

2 1

1 1 1

2 5

limit.in2:

1 0

-1 3

2

limit.in3:

0 1

1

1 0

limit.in4:

2 2

2 1 6

4 5 -7

limit.in5:

1 1

9 0

-5 2

样例输出

limit.out1:

Infinity

limit.out2:

-Infinity

limit.out3:

0/1

limit.out4:

1/2

limit.out5:

-9/5

数据范围限制

对于100%的数据:0<=n,m<=100,|ai|,|bi|<10^5。


看数据可以发现,数值是由两行的第一个数决定的。
如果一正一负则输出-号
如果n>m则输出Infinity
如果n=m则将a[1]和b[1]约分后输出,要记得输出符号
如果n小于m则输出0/1


代码如下:

var   n,m,x,y:longint;
      bool1,bool2:boolean;

procedure yue;
var i:longint;
begin
  for i:=2 to x do
    if (x mod i=0)and(y mod i=0) then
      begin
        x:=x div i;
        y:=y div i;
      end;
end;

begin
  assign(input,'limit.in');
  assign(output,'limit.out');
  reset(input);
  rewrite(output);
  readln(n,m);
  readln(x);
  readln(y);
  if x<0 then bool1:=true else bool1:=false;
  if y<0 then bool2:=true else bool2:=false;
  x:=abs(x); y:=abs(y);
  if n>m then
    begin
      if (bool1=true)and(bool2=false)or(bool1=false)and(bool2=true) then write('-');
      write('Infinity');
    end
  else
    if n=m then
      begin
        yue;
        if (bool1=true)and(bool2=false)or(bool1=false)and(bool2=true) then write('-');
        write(x,'/',y);
      end
    else write(0,'/',1);
  close(input);
  close(output);
end.

第三题

题目描述

小x有两个长度均为n的字符串s和w。小x认为s和w是不可比较的,当存在i和j (0<=i,j<=n),si>wi并且sj< wj。si表示字符串s中的第i个元素,相似的,wj表示字符串w中第j个元素。

字符串模板由数字和问号“?”构成,“?”并不会成对出现。

小x现在有两个长度为n的字符串模板。每个问号可以填不同的数或相同的数,小x想要计算填数的方案数,使得这两个字符串不可比较。最终得到的字符串可以包含前导零。

帮助小x计算出方案数除以1000000007的余数。

输入

第一行一个整数n,表示字符串模板的长度。

第二、第三行,每行包含一个长度为n的字符串模板。

输出

一行一个整数,方案数除以1000000007的余数。

样例输入

strings.in1:

2

90

09

strings.in2:

2

11

55

strings.in3:

5

?????

?????

样例输出

strings.out1:

1

strings.out2:

0

strings.out3:

993531194

数据范围限制

对于20%的数据 :1<=n<=5

对于50%的数据: 1<=n<=25

对于100%的数据: 1<=n<=10^5


这题是分五种情况去判断
①如果st1[i]和st2[i]都是’?’则a[i,1]:=a[i-1,1]*55(即0~9,1~9……9)
a[i,2]同上
总方案数ans*100
②如果st1[i]=’?’和st2[i]<>’?’a[i,1]:=a[i-1,1]*(10-st2[i] (数值))
a[i,2]:=a[i,2-1]*(st2[i] (数值)+1) ans:=ans *10
③如果st1[i]<>’?’和st2[i]=’?’,其原理如上
④如果st1[i]<>’?’和st2[i]<>’?’ 而且st1[i]>st2[i]则将a[i,1]:=a[i-1,1]
⑤如果st1[i]<>’?’和st2[i]<>’?’ 而且st1[i]

const mod1=1000000007;

var  n,i,x,ans,l,y:longint;
     st1,st2:ansistring;
     f:array[0..100000,1..2]of longint;

begin
  assign(input,'strings.in');
  assign(output,'strings.out');
  reset(input);
  rewrite(output);
  readln(n);
  f[0,1]:=1; f[0,2]:=1;
  readln(st1);
  readln(st2);
  ans:=1;
  y:=1;
  l:=0;
  for i:=1 to n do
    if (st1[i]=st2[i])and(st1[i]='?') then
      begin
        f[i,1]:=(int64(f[i-1,1])*55) mod mod1;
        f[i,2]:=(int64(f[i-1,2])*55) mod mod1;
        ans:=(int64(ans)*10*10) mod mod1;
        inc(l);
      end
    else
      if (st1[i]='?') then
        begin
          val(st2[i],x);
          f[i,1]:=(int64(f[i-1,1])*(10-x)) mod mod1;
          f[i,2]:=(int64(f[i-1,2])*(x+1)) mod mod1;
          ans:=(int64(ans)*10) mod mod1;
        end
      else
        if st2[i]='?' then
          begin
            val(st1[i],x);
            f[i,1]:=(int64(f[i-1,1])*(x+1)) mod mod1;
            f[i,2]:=(int64(f[i-1,2])*(10-x)) mod mod1;
            ans:=(int64(ans)*10) mod mod1;
          end
        else
          if st1[i]>st2[i] then f[i,1]:=f[i-1,1] else f[i,2]:=f[i-1,2];
  ans:=ans-f[n,1]-f[n,2];
  if (f[n,1]>0)and(f[n,2]>0) then
    begin
      for i:=1 to l do y:=(int64(y)*10) mod mod1;
      ans:=ans+y;
    end;
  if ans<0 then ans:=ans+mod1;
  write(ans);
  close(input);
  close(output);
end.

第四题

题目描述

  小x有一个由n个顶点构成的加权有向图,这张图中,任意两个顶点之间的都有两条方向不同的边。小x很喜欢玩图,现在他发明了一个新的游戏:

  这个游戏共有n步。

  在第i步时,小x把第xi个点从图中删除,同时删除所有与xi相连的边,包括xi的入边和出边。

  每步操作进行前,小x想知道所有剩余顶点之间的最短路径的长度之和,最短路径可以通过任何剩余的顶点。换句话说,我们定义d(i,v,u)是在删除顶点xi之前,顶点v到顶点u的最短路径。

输入

第一行包含一个整数n,表示图的顶点数。

接下来n行,每行n个整数,第i行第j个元素aij表示顶点i到顶点j的边的权值。

最后一行,包含n个不同的整数:x1,x2,…,xn(1<=xi<=n),表示小x删的顶点。

输出

一行用1个空格分开的n个整数,第i个数表示在第i步前所求的值。行末没有多余的空格。

样例输入

shortest.in1:

1

0

1

shortest.in2:

2

0 5

4 0

1 2

shortest.in3:

4

0 3 1 1

6 0 400 1

2 4 0 1

1 1 1 0

4 1 2 3

样例输出

shortest.out1:

0

shortest.out2:

9 0

shortest.out3:

17 23 404 0

数据范围限制

对于30%的数据:1<=n<=50

对于70%的数据:1<=n<=100

对于100%的数据:1<=n<=500,1<=xi<=n,1<=aij<=10^5,aii=0


这题如果直接弗洛伊德可能数值会有很多重复
所以
我们从最后删掉的点一直往会搜到没有删点
每次增加一个点,再判断这个点加进来有没有比原来的最短路径还短的路径,更新数值。直到没有删点。


代码如下:

var  n,i,j,k:longint;
     a:array[0..505,0..505]of longint;
     b,ans:array[0..1010]of longint;
begin
  assign(input,'shortest.in');
  assign(output,'shortest.out');
  reset(input);
  rewrite(output);
  readln(n);
  for i:=1 to n do
    begin
      for j:=1 to n do read(a[i,j]);
      readln;
    end;
  for i:=1 to n do read(b[i]);
  for k:=n downto 1 do
    begin
      for i:=1 to n do
        for j:=1 to n do
          begin
            if a[b[i],b[k]]+a[b[k],b[j]]<a[b[i],b[j]] then a[b[i],b[j]]:=a[b[i],b[k]]+a[b[k],b[j]];
            if (i>=k)and(j>=k) then ans[k]:=ans[k]+a[b[i],b[j]];
          end;
    end;
  for i:=1 to n do write(ans[i],' ');
  close(input);
  close(output);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值