jzoj C组 2017.1.15比赛

来源:互联网 发布:谷歌网络博物馆 编辑:程序博客网 时间:2024/05/17 06:56

第一题

题目描述

小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.
1 0