MDeath-Kid

- M I T & Y
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

USTH-ACM校选拔赛试题报告

Posted on 2011-09-12 13:25  MDeath-Kid  阅读(314)  评论(2)    收藏  举报

一共10个题目。

前几个都是考基本流程控制的大水题。

第一题,格式输入,条件判断。

1001
 1 #include<iostream>
2 #include<stdio.h>
3 #include<string.h>
4 #include<limits.h>
5 #include<queue>
6 #include<algorithm>
7 #define FOPEN freopen("d:\\1.txt","r",stdin);
8 #define MAXN 10005
9
10 using namespace std;
11
12 int main() {
13 int a,b,ans;
14 char c;
15 while(~scanf(" %d%c%d=",&a,&c,&b)) {
16 switch (c) {
17 case '+':
18 ans = a + b;
19 break;
20 case '-':
21 ans = a - b;
22 break;
23 case '*':
24 ans = a * b;
25 break;
26 case '/':
27 ans = a / b;
28 break;
29 }
30 printf("%d\n",ans);
31 }
32 }

 

第二题细心一点就行了,想好各种情况。//情况再多就是if else 判断

#include<iostream>
#include
<stdio.h>
#include
<string.h>
#include
<limits.h>
#include
<algorithm>
#define FOPEN freopen("d:\\1.txt","r",stdin);
#define MAXN 10005

using namespace std;

int main() {
int a,b;
while(~scanf("%d:%d",&a,&b)) {
b
++;
if(b>59) b=0,a++;
if(a>23) a=0;

if(a<10) printf("0%d:",a);
else printf("%d:",a);
if(b<10) printf("0%d\n",b);
else printf("%d\n",b);
}
}

 

找到规律,一步步操作就行了,放在数组里面是个比较简单的方法。

1002
 1 #include<iostream>
2 #include<stdio.h>
3 #include<string.h>
4 #include<limits.h>
5 #include<algorithm>
6 #define FOPEN freopen("d:\\1.txt","r",stdin);
7 #define MAXN 10005
8
9 using namespace std;
10
11 char mat[105][105]; //把要打印的X ‘8’ 放在数组里面
12 int main() {
13 int n;
14 while(~scanf("%d",&n)) {
15 memset(mat,' ',sizeof(mat));
16
17 //两步对角线赋值操作
18 for(int i = 0;i<n;i++) {
19 mat[i][i] = '8';
20 mat[i][abs(n-1-i)] = '8';
21 }
22
23 //打印
24 for(int i = 0;i<n;i++){
25 for(int j = 0;j<n;j++) {
26 printf("%c",mat[i][j]);
27 }
28 puts("");
29 }
30 }
31 }

 

用一个求和公式直接进行求和,然后mod 9 就行了。

1004
 1 #include<iostream>
2 #include<stdio.h>
3 #include<string.h>
4 #include<limits.h>
5 #include<algorithm>
6 #define FOPEN freopen("d:\\1.txt","r",stdin);
7 #define MAXN 10005
8
9 using namespace std;
10
11 int main() {
12 int n;
13 while(~scanf("%d",&n)) {
14 printf("%d\n",((n * (n + 1))/2) % 9);
15 }
16 }

 

数论题目。1005是个公式,最大值就是 (n-1)/(n+1),推出来就能做出来。但是主要,这个分数是即约分数,就是能约分就要约分。

1005
 1 #include<iostream>
2 #include<stdio.h>
3 #include<string.h>
4 #include<limits.h>
5 #include<algorithm>
6 #define FOPEN freopen("d:\\1.txt","r",stdin);
7 #define MAXN 10005
8
9 using namespace std;
10
11 //递归求GCD,效率略大于 辗转相除的循环求GCD
12 int gcd(int x,int y){
13 return y==0?x:gcd(y,x%y);
14 }
15
16 int main() {
17 int n;
18 while(~scanf("%d",&n)) {
19 int fenzi = n-1;
20 int fenmu = n+1;
21
22 //能不能约分,求分子分母的最大公约数
23 int cnt = gcd(fenzi,fenmu);
24 printf("%d/%d\n",fenzi/cnt,fenmu/cnt);
25 }
26 }

 

排序,你用什么都行,比较简单冒泡,选择,归并,或者效率较高的希尔和快排,推荐用快排,只有不涉及外部排序,都用快排!

(这里我直接用库函数了,冒泡可以自己去试着写写)

1006
 1 #include<iostream>
2 #include<stdio.h>
3 #include<string.h>
4 #include<limits.h>
5 #include<algorithm>
6 #define FOPEN freopen("d:\\1.txt","r",stdin);
7 #define MAXN 15
8
9 using namespace std;
10
11 struct stu{
12 char name[10];
13 int scor;
14 }st[MAXN];
15
16 int cmp(const void *a,const void *b){
17 stu *c = (stu *)a;
18 stu *d = (stu *)b;
19 return d ->scor - c ->scor;
20 }
21
22 int main() {
23 int n;
24 while(~scanf("%d",&n)) {
25 for(int i = 0;i<n;i++) {
26 scanf(" %s %d",st[i].name,&st[i].scor);
27 }
28
29 //初次可能难以掌握qsort的用法,但他是一个很好的函数,不懂的去百度百科
30 qsort(st,n,sizeof(st[0]),cmp);
31
32 for(int i = 0;i<n;i++) {
33 printf("%s %d\n",st[i].name,st[i].scor);
34 }
35 }
36 }

 

 

这个题目是一个和素数有关的地方,每一行的最后一个都是素数,而且记住,数论上的所有东西都是以素数展开的!

常见的数论知识:中国剩余定理,欧几里得,扩展欧几里得,模线性方程,丢潘图方程。

素数有无穷多个,到目前为止没有一个素数产生方程,能产生所有的素数,所以几千年来吸引了很多很多的数学爱好者,RSA加密就基于一个大的合数很难被因式分解。

常见的结论:如果p是个素数 而且p+2也是素数,则称为一个素数对,素数对有无穷多个。(陈景润给出的证明)

两个素数之间可以有任意多个合数。

目前为止找到的最大的素数都是通过梅森素数找到的。

RSA解密和找到更大的素数是一个全球范围内的活动,有奖金,而且能一下成名。

费马定理在07年(左右,忘记了)被一个数学家用了8年时间切掉了~~ 验证他的证明用了一年时间,有很多人写小说,就是数学家证明一个定理的岁月,很是让人高山仰止啊~(那一年全球的新闻头条都是这个,这个问题困扰了500多年)。

就想到这些,喜欢的可以看看Rosen的《初等数论》,看书尽量看外国人写的书,能受益终身,至少计算机方面的。

//

程序先打素数表,在判断。

1007
 1 #include<stdio.h>
2 #include<iostream>
3 #include<limits.h>
4 #include<string.h>
5 using namespace std;
6
7 #define MAXN 1000
8
9 bool a[MAXN];
10
11 //先素数帅选。
12 void init() {
13 //初始化
14 memset(a,true,sizeof(a));
15
16 //筛选
17 a[1] = 0;
18 for(int i = 2;i<MAXN;i++){
19 if(a[i]) {
20 for(int j = i + i;j<MAXN;j+=i)
21 a[j] = 0,
22 cout<<j<<endl;
23 }
24 }
25 }
26
27 int main() {
28
29 init();
30
31 //这时候 a 数组里面值为真的即为素数,放到另一个数组里面
32 int prim[MAXN],p=0;
33 for(int i = 2;i<MAXN;i++) {
34 if(a[i]) {
35 prim[p++] = i;
36 cout<<i<<endl;
37 }
38 }
39 int n;
40 while(~scanf("%d",&n)) {
41
42 //x y 记录坐标
43 int x,y;
44 if(n == 1) {x = 1,y = 1;}
45 else if(n == 2) {x = 1;y = 2;}
46 //接下来进行找就行了,可以是二分查找,或者普通的查找
47 else {
48 for(int i = 0;i<p-1;i++) {
49 if(n > prim[i] && n <= prim[i+1]) { //这里的 = 放在那里,要想清楚
50 x = i+2;
51 y = n - prim[i] ;
52 }
53 }
54 }
55 printf("(%d,%d)\n",x,y);
56 }
57 }

 

1008是个经典的分数拆分问题。

LY出的题目,一开始没想出来……囧

(经过我们班同学的提示,想到了,但是很悲剧的是我居然不能给出证明,留给大家思考了,我也在想想,这类题目也很多。)(这个想法太麻烦了,就用下面的枚举就行了)

稍稍变形 (y-k)/(y*k) = 1/x

我的做法,枚举第二个数,判断(y-k)/(y*k)能不能约分为一,就行了。

设GCD(x,y)为 x,y的最大公约数。

如果能约分那么必有GCD(GCD(y-k,y*k),y-k) == y-k;

 判断输出就行了。

1008
 1 #include<stdio.h>
2 #include<iostream>
3 #include<limits.h>
4 #include<string.h>
5 using namespace std;
6
7 #define MAXN 1000
8
9 int gcd(int x,int y) {
10 return y==0?x:gcd(y,x%y);
11 }
12
13 int n;
14
15 int main() {
16 while(~scanf("%d",&n)) {
17 for(int i = n+1;i<=2*n;i++) {
18 int m = gcd(i*n,i-n);
19 if(gcd(m,i-n) != (i-n)) continue;
20 printf("1/%d = 1/%d + 1/%d\n",n,(n*i)/m,i);
21 }
22 }
23 }

1009其实挺简单的,就是一个想法的题目,让时间最少的那个人站最前面就是总共的最少时间,先排序,然后向后面+时间就行了,不写代码了。

 

1010是一道很经典的题目,大家应该好好看一下,这个题目涉及一个很重要的数列!

 

1 是初始状态。    1 - 1 : 1

2 可以从 1 走来    1 - 2:1

3 可以从 1 - 2 走来  1 - 3 :2

4 可以从 2 - 3 走来  1 - 4 :3

5 可以从 3 - 4 走来  1 - 5 :5

……

你会发现这个数只能从前两个数走来,用f(n)表示从1-n用的步数,则f(n) = f(n-1) + f(n-2);

这就是有名的 斐波那契数列 (有名,可能对你们很陌生)(斐波那契是一个意大利的数学家,专注于几何和丢潘图)

介绍一下几个小结论:

f(1) + f(2) + f(3) ……+f(n) = f(n+2);

f(n+3) + f(n) = f(n+2) * 2;

f(n + 3) - f(n) = f(n-1) * 2;

f(2n) = f(n) * f(n) + 2 * f(n-1) * f(n);

大家可以试着去证明证明,都挺简单的证明。

还有很多很多的等式,而且这个数列的应用巨广,以后设计到它的会有很多。(不单单在数论上面,甚至在几何,组合数学,化学等等都能看见他的身影,等你发现的时候你会感叹他就是一神~)

对了如果这个题目输入 3 6 怎么办?

大家自己想一想,也不贴代码了,这个很好求答案。

 

大家初入ACM的殿堂,真正算法的乐趣只有研究进去了才能体会,非常想让大家多多了解ACM,因为这是一个很好的平台!