2012年南京市复赛模拟测试题(普及)
题目 |
统计差异数 |
树顶点标号 |
分班 |
联络 |
程序名(*. pas/c/cpp) |
dec |
labeling |
orz |
biu |
输入文件 |
dec.in |
labeling.in |
orz.in |
biu.in |
输出文件 |
dec.out |
labeling.out |
orz.out |
biu.out |
用时 |
1s |
1s |
1s |
1s |
内存限定 |
128M |
128M |
128M |
128M |
第一题:统计差异数(dec)
【问题描述】
国家统计局每年都对各城市的人的收入进行调查统计。针对不同人群之间收入差异度进行的统计。一般统计方法是:对不同人群收入进行求差,符合规定差值的数目统计出来。
【输入格式】
第一行包括2个非负整数N(不同的人群数)和C(差值),中间用空格隔开。
第二行有N个整数(每个人群的收入),中间用空格隔开。
【输出格式】
输出一行,表示人群差值为C的数对的个数。
【输入样例】
4 1
1 1 2 3
【输出样例】
3
【数据规模】
对于90%的数据,N <= 2000;
对于100%的数据,N <= 200000。
所有输入数据都在longint范围内。
【算法分析】
算法1:朴素算法
此题无标程,我就不说我直接暴力+优化的,看看题解肯定就能写出来的- -,就不放我的程序了 。
第二题:树顶点标号(Labeling)
【问题描述】
Maximum最近学习了有关多叉树的知识。如果存在这样一颗树,其所有的叶子节点的深度都相同,并且所有非叶子节点都有K个子节点,我们就称这颗树为满K叉树。显然,如果我们知道K和这颗满K叉树的深度d,我们很容易就能计算出这颗树的节点总数,不妨记为N。
Maximum突然想出了这样一个问题:假设我们对这些节点进行1至N标号。如果在一种标号方案中,任意一个节点的标号都大于其所有祖先节点的标号,我们就称当前的标号方案为合法的。
那么,如果已知K和d,一共有多少种合法的标号方案呢?Maximum请你编程帮他算一算。
【输入格式】
输入文件中包含两个数字K和d(根高度为零),意义如上文所述。
【输出格式】
输出文件中应该仅有一个数字,表示合法的标号方案个数。
【输入样例】
2 2
【输出样例】
80
【数据规模】
1 ≤ K * d ≤ 21
【算法分析】推推公式,应该可以得到以下结论ans=n!/(∏f[i])
【标程】
2
3 k , d, i, j, z ,q ,ws : integer;
4 jw :int64;
5 a : array[ 1..6000 ] of integer;
6 x, y : array[ 0..21 ] of integer;
7 ans : array[ 1..9180 ] of 0..9;
8 begin
9 assign( input, 'labeling.in' ); reset( input );
10 assign( output, 'labeling.out' ); rewrite( output );
11 readln( k, d );
12 x[ 0 ] := 1;
13 for i := 1 to d do
14 x[ i ] := x[ i - 1 ] * k + 1;
15 y[ d ] := 1;
16 for i := d - 1 downto 1 do
17 y[ i ]:= y[ i + 1 ] * k;
18 dec( x[ d ] );
19 for i := 1 to x[ d ] do
20 a[ i ] := i;
21 dec( d );
22 for i := 1 to d do
23 while x [ i ] <>1 do begin
24 for q := 2 to x[ i ] do
25 while x[ i ] mod q = 0 do begin
26 x[ i ] := x[ i ] div q;
27 for j := 1 to y[ i ] do
28 begin
29 z := x[ d + 1 ];
30 while a[ z ] mod q <>0 do dec( z );
31 a[ z ] := a[ z ] div q;
32 end;
33 end;
34 end;
35 inc( d );
36 fillchar( ans, sizeof( ans ), 0 );
37 ans[ 1 ] := 1; ws := 1;
38 for i := 1 to x[ d ] do
39 begin
40 jw := 0;
41 for j := 1 to ws do begin
42 jw := jw + ans[ j ] * a[ i ];
43 ans[ j ]:= jw mod 10;
44 jw := jw div 10;
45 end;
46 while jw <> 0 do begin
47 inc( ws );
48 ans[ ws ] := jw mod 10;
49 jw := jw div 10;
50 end;
51 end;
52 for i := ws downto 1 do
53 write( ans[ i ] );
54 writeln;
55 close( input ); close( output );
56 end.
第三题: 分班(orz)
【问题描述】新学期马上就要开学了,学校让小憨为新生进行分班。因考虑上好体育课,分班的原则比较特别,要么保证整个班级都是同一性别,要么男女性别人数差不超过M。另外,现在N位同学排成一排,小憨只会把连续一段的同学分进一个班级。学校想知道,至少需要分出多少个班级。
【输入格式】
输入文件第一行包括N和M。
之后N行,每行一个整数,1表示男生,2表示女生。
【输出格式】
输出一个整数,表示最小分出班级的数量。
【输入样例】
5 1
2
2
1
2
2
【输出样例】
2
【数据规模】
对于30%的数据,有1 ≤ N ,M≤ 50;
对于100%的数据,有1 ≤ N,M ≤ 2500。
【算法分析】
【标程】
2 q,p,i,j,n,m:longint;
3 qq,pp,s,a:array[0..3000]of longint;
4 c:char;
5 procedure refresh(i,j:longint);
6 begin
7 if (a[i+j]>a[i]+1)or(a[i+j]=-1) then a[i+j]:=a[i]+1;
8 end;
9 begin
10 assign(input,'orz10.in');reset(input);
11 assign(output,'orz10.out');rewrite(output);
12 readln(n,m);
13 for i:=1 to n do
14 begin
15 readln(c);
16 if c='1' then s[i]:=1 else s[i]:=2;
17 end;
18 for i:=1 to n do
19 begin
20 qq[i]:=qq[i-1];
21 pp[i]:=pp[i-1];
22 if s[i]=1 then inc(qq[i]) else inc(pp[i]);
23 end;
24 fillchar(a,sizeof(a),255);
25 a[0]:=0;
26 for i:=0 to n-1 do
27 for j:=1 to n-i do
28 if (qq[j+i]-qq[i]=0)or(pp[j+i]-pp[i]=0)or(abs(qq[j+i]-qq[i]-pp[j+i]+pp[i])<=m) then refresh(i,j);
29 writeln(a[n]);
30 close(input);
31 close(output);
32 end.
33
第四题:天才的记忆(Talentm)
【问题描述】
从前有个人名叫W and N and B,他有着天才般的记忆力,他珍藏了许多许多的宝藏。在他离世之后留给后人一个难题(专门考验记忆力的啊!),如果谁能轻松回答出这个问题,便可以继承他的宝藏。
题目是这样的:给你一大串数字(编号为1到 N,大小可不一定哦!),在你看过一遍之后,它便消失在你面前,随后问题就出现了,给你M个询问,每次询问就给你两个数字A,B,要求你瞬间就说出属于A到B这段区间内的最大数。一天,一位美丽的姐姐从天上飞过,看到这个问题,感到很有意思(主要是据说那个宝藏里面藏着一种美容水,喝了可以让这美丽的姐姐更加迷人),于是她就竭尽全力想解决这个问题。BUT,她每次都以失败告终,因为这数字的个数是在太多了!于是她请天才的你帮他解决。如果你帮她解决了这个问题,可是会得到很多甜头的哦!
【输入格式】
一个整数N表示数字的个数,接下来一行为N个数。第三行读入一个M,表示你看完那串数后需要被提问的次数,接
下来M行,每行都有两个整数A,B。
【输出格式】
输出共M行,每行输出一个数。
【输入样例】
6
34 1 8 123 3 2
4
1 2
1 5
3 4
2 3
【样例输出】
34
123
123
8
【数据规模】
对于30%的数据,1<=N<=10000,1<=M<=100
对于100%的数据,1<=N<=200000,1<=M<=10000.
【算法分析】
经典的RMQ问题,亦可用线段树解决,是VIJOS上的原题,类似于TYVJ忠诚。
【我的程序】
2 a,b,x,y:array[1..200000] of longint;
3 procedure sortquick(l,r:longint);
4 var i,j,x,y:longint;
5 begin
6 i:=l;j:=r;
7 x:=a[(l+r) div 2];
8 repeat
9 while a[i]>x do inc(i);
10 while x>a[j] do dec(j);
11 if i<=j then
12 begin
13 y:=a[i];
14 a[i]:=a[j];
15 a[j]:=y;
16 y:=b[i];
17 b[i]:=b[j];
18 b[j]:=y;
19 inc(i);
20 dec(j);
21 end;
22 until i>j;
23 if i<r then sortquick(i,r);
24 if l<j then sortquick(l,j);
25 end;
26 begin
27 assign(input,'Talentm.in');
28 reset(input);
29 assign(output,'Talentm.out');
30 rewrite(output);
31
32
33 readln(m);
34 for i:=1 to m do begin read(a[i]); b[i]:=i; end;
35 readln(n);
36 for i:=1 to n do readln(x[i],y[i]);
37 sortquick(1,m);
38 for j:=1 to n-1 do
39 for i:=1 to m do
40 if (b[i]>=x[j]) and (b[i]<=y[j]) then
41 begin
42 writeln(a[i]);
43 break;
44 end;
45 for i:=1 to m do
46 if (b[i]>=x[n]) and (b[i]<=y[n]) then
47 begin
48 writeln(a[i]);
49 break;
50 end;
51 close(output);
52 close(input);
53 end.
【标程】
2 maxlogn=17;
3
4 var RMQ:array[0..maxn,0..maxlogn]of longint;
5 log2:array[1..maxn]of longint;
6 n,m:longint;
7
8 function max(a,b:longint):longint;
9 begin
10 if a>b then
11 max:=a
12 else
13 max:=b;
14 end;
15
16 procedure main;
17 var i,j,k,l:longint;
18 begin
19 assign(input,'Talentm.in');
20 assign(output,'Talentm.out');
21 reset(input);
22 rewrite(output);
23 readln(n);
24 for i:=1 to n do read(RMQ[i,0]);
25 k:=0;
26 for i:=1 to n do
27 begin
28 if 1 shl (k+1)=i then inc(k);
29 log2[i]:=k;
30 end;
31 k:=log2[n];
32 for j:=1 to k do
33 for i:=1 to n-(1 shl j)+1 do
34 RMQ[i,j]:=max(RMQ[i,j-1],RMQ[i+1 shl (j-1),j-1]);
35 readln(m);
36 for l:=1 to m do
37 begin
38 read(i,j);
39 k:=log2[j-i+1];
40 writeln(max(RMQ[i,k],RMQ[j-(1 shl k)+1,k]));
41 end;
42 close(input);
43 close(output);
44 end;
45
46 begin
47 main;
48 end.