[关闭]
@donghanyuan0609 2023-03-18T16:08:00.000000Z 字数 7172 阅读 118

2018级航空航天类《C语言程序设计》上机考试 A卷试题(回忆版)

以下提供的 AC 代码可能不是最简的思路和代码实现,仅供参考!

A 向量的模长

试题大意

输入一个 n 维向量,求这个向量的模长的平方

样例输入

  1. 3
  2. 1 2 3

样例输出

  1. 14

AC代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. int n;
  7. int a[1005];
  8. int len()
  9. {
  10. int s = 0;
  11. int i;
  12. for (i = 0; i < n; i++)
  13. s += a[i] * a[i];
  14. return s;
  15. }
  16. int main()
  17. {
  18. int i;
  19. scanf("%d", &n);
  20. for (i = 0; i < n; i++)
  21. scanf("%d", &a[i]);
  22. printf("%d\n", len());
  23. return 0;
  24. }

作答提示

要求求的是模长的平方,得到的结果直接就是整数,不需要用浮点数,不需要开平方。

更进一步,对顺序输入的元素求平方和可以不需要数组。更简单的参考代码:

  1. #include <stdio.h>
  2. int main() {
  3. int n, i, x, s = 0;
  4. scanf("%d", &n);
  5. for (i = 0; i < n; i++) {
  6. scanf("%d", &x);
  7. s += x * x;
  8. }
  9. printf("%d\n", s);
  10. return 0;
  11. }

B 质因数分解

题目大意

给定一个整数 p,保证该数是 2 个质数的乘积(即 ),求较大的质因子

样例输入

  1. 21

样例输出

  1. 7

AC代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. int main()
  7. {
  8. int n, i;
  9. scanf("%d", &n);
  10. for (i = 2; i <= sqrt(n); i++)
  11. {
  12. if (n % i == 0)
  13. break;
  14. }
  15. printf("%d\n", n / i);
  16. return 0;
  17. }

作答提示

这道题给的限定条件相当严格,所以其实可用来输入的整数的个数是相当有限的。千万不要担心有不符合 的输入数据。要求输出 可以先找出 (因为 比较小,比较容易找,找的范围是到 即可)。

直接从 2 循环到 n 也是可以的,因为遇到 break 了,实际的循环不会真正执行到 以后。

C 加权平均分

题目大意

给出一些门课的得分(百分制)和这门课的学分数,求加权平均分。输入为每行 2 个整数,分别表示一门课程的学分数量和百分制得分。输出加权平均分保留 2 位小数

特别注意:如果总学分数为零,则加权平均为零分0.00 )。

样例输入

  1. 6 98
  2. 4 93
  3. 2 88

样例输出

  1. 94.67

AC代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. int a[105], v[105];
  7. int sumv, sum;
  8. int main()
  9. {
  10. int ai, vi;
  11. while (scanf("%d%d", &vi, &ai) != EOF)
  12. {
  13. sum += ai * vi;
  14. sumv += vi;
  15. }
  16. if (sumv) printf("%.2lf\n", sum * 1.0 / sumv);
  17. else printf("0.00\n");
  18. return 0;
  19. }

作答提示

输入数据是没有给学科数量的,也就是输入的行数是 不确定 的,请用 while(scanf(...) != EOF) 输入数据。另外,在本机调试的过程中,当你输入完所有的数据,程序是不会马上有反应的,因为你没有给出n,计算机不知道你输入的数据到底有多少行,所以会一直等着你输入。此时请用 Ctrl+Z 终止输入(控制台会显示一个符号 ^Z,然后再按回车就可以看到输出结果了),^Z 这个符号代表 EOF

另外注意判断总学分数是否为零。第一次忘了加判断就 WA 了一个点。

D 十六进制编辑器

题目大意

十六进制(大写),2 位一组给出 n8-bit 整数(以一行字符串的形式给出)。

有若干组查询,每个查询给出 两个整数,要输出第 个数和第 个数的乘积(十进制)。

输入数据第一行是 ;第二行是一个长度为 的字符串(仅包含数字和大写字母 A-F);第三行是 表示 次查询,接下来 行每行 2 个整数

对于每次查询,输出一个整数,为第 个数和第 个数的乘积(下标从零开始)

样例输入

  1. 8
  2. 8AE45CF173BB6A2E
  3. 5
  4. 1 4
  5. 0 2
  6. 2 7
  7. 3 6
  8. 4 5

样例输出

  1. 26220
  2. 12696
  3. 4232
  4. 25546
  5. 21505

AC代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. int hextodec(char x1, char x2)
  7. {
  8. int d1, d2;
  9. if (isdigit(x1))d1 = x1 - '0';
  10. else if (x1 >= 'A' && x1 <= 'F')d1 = x1 - 'A' + 10;
  11. if (isdigit(x2))d2 = x2 - '0';
  12. else if (x2 >= 'A' && x2 <= 'F')d2 = x2 - 'A' + 10;
  13. return d1 * 16 + d2;
  14. }
  15. int n, m;
  16. int a[10005];
  17. int main()
  18. {
  19. int i;
  20. char c1, c2;
  21. int x, y;
  22. scanf("%d", &n);
  23. while (getchar() != '\n');
  24. for (i = 0; i < n; i++)
  25. {
  26. c1 = getchar();
  27. c2 = getchar();
  28. a[i] = hextodec(c1, c2);
  29. }
  30. scanf("%d", &m);
  31. for (i = 0; i < m; i++)
  32. {
  33. scanf("%d%d", &x, &y);
  34. printf("%d\n", a[x] * a[y]);
  35. }
  36. return 0;
  37. }

作答提示

先把输入的长度为 的字符串所表达的 个十六进制整数存入 int 数组,然后处理对于乘积的查询。

E 忽略大小写的子串匹配

题目大意

给俩字符串,一行一个(均不包含空白字符),判断第一个字符串是不是第二个字符串的子串,如果是的话输出子串最先出现的位置,如果不是子串输出错误信息。

样例输入

  1. hAnG
  2. BeiHangUniversity
  1. BuAA
  2. ACcoding.cn

样例输出

  1. Yes:4
  1. Emmm

AC代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. char key[1005], str[1005];
  7. char key2[1005], str2[1005]; //lowercase
  8. int main()
  9. {
  10. int i;
  11. char *ret = NULL;
  12. scanf("%s", key);
  13. scanf("%s", str);
  14. for (i = 0; key[i]; i++)
  15. key2[i] = tolower(key[i]);
  16. for (i = 0; str[i]; i++)
  17. str2[i] = tolower(str[i]);
  18. ret = strstr(str2, key2);
  19. if (ret != NULL)
  20. printf("Yes:%d\n", ret - str2 + 1);
  21. else
  22. printf("Emmm\n");
  23. return 0;
  24. }

作答提示

因为题目说了字符串不带空白字符,所以不要用 gets ,优先选用 scanf 。如果用了 gets 一定要检验字符串末尾有没有 '\r' ,否则会错的很惨。 Windows 系统和 Linux 系统的默认换行符不同,想要详细了解可以问助教或者上网查。

用库函数 strstr 匹配子串,要熟悉。此题由于忽略大小写,所以将输入的字符串全部转换为小写再匹配。

F 扫雷

题目大意

给一个 的字符方阵,每个格有地雷或者没有地雷,然后输出一个 的整数方阵,求出每个格子周围的地雷数量(以该格子为中心的九宫格内地雷数量)

我忘了"没有地雷"是什么符号表示了,可能是 '.' 或者 'N' 吧,然后有地雷的符号根据我的AC代码反推回去应该是用 'Y' 表示的。

样例输入

  1. 3 4
  2. ..Y.
  3. .Y..
  4. Y...

样例输出

  1. 1 2 2 1
  2. 2 3 2 1
  3. 2 2 1 0

AC代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. int n, m;
  7. char mp[105][105];
  8. int cnt[105][105];
  9. typedef struct Point
  10. {
  11. int x, y;
  12. }Point;
  13. Point nil, dir[9] = {
  14. {-1,-1}, {-1, 0}, {-1, 1},
  15. {0, -1}, {0, 0}, {0, 1},
  16. {1, -1}, {1, 0}, {1, 1}
  17. };
  18. Point mkpt(int x, int y)
  19. {
  20. Point ret;
  21. ret.x = x, ret.y = y;
  22. return ret;
  23. }
  24. Point padd(Point a, Point b)
  25. {
  26. Point ret;
  27. ret.x = a.x + b.x;
  28. ret.y = a.y + b.y;
  29. return ret;
  30. }
  31. int inLim(Point ct)
  32. {
  33. return (ct.x >= 0 && ct.x < n) && (ct.y >= 0 && ct.y < m);
  34. }
  35. int cntt(Point ct)
  36. {
  37. int i, ret = 0;
  38. for (i = 0; i < 9; i++)
  39. {
  40. Point pt = padd(ct, dir[i]);
  41. if (inLim(pt) && mp[pt.x][pt.y] == 'Y')
  42. ret++;
  43. }
  44. return ret;
  45. }
  46. int main()
  47. {
  48. int i, j;
  49. scanf("%d%d", &n, &m);
  50. for (i = 0;i < n; i++)
  51. scanf("%s", mp[i]);
  52. for (i = 0; i < n; i++)
  53. for (j = 0; j < m; j++)
  54. cnt[i][j] = cntt(mkpt(i, j));
  55. for (i = 0; i < n; i++)
  56. for (j = 0; j < m; j++)
  57. printf("%d%c", cnt[i][j], j == m-1 ? 10 : 32);
  58. return 0;
  59. }

作答提示

循环,然后注意一下如何处理边界。

输出的时候每行 m 个整数,中间空格隔开,最后尽量不要留多余的空格(不确定会不会PE)。

G 扑克统计

题目大意

给一堆扑克牌的信息,统计当前桌面上现有的牌能凑出几套完整的扑克牌。

多组输入数据

每组输入数据先给一个 n 表示当前桌面上牌的张数,然后每行 2 个整数,分别表示花色(1 到 4 的整数)和牌面(1 到 13 的整数)。输出一个整数表示能凑出来多少张牌。

一副完整扑克牌的标准是 52 张,四种花色每种 13 张。

样例输入

  1. 2
  2. 13
  3. 1 1
  4. 1 2
  5. 1 3
  6. 1 4
  7. 1 5
  8. 1 6
  9. 1 7
  10. 1 8
  11. 1 9
  12. 1 10
  13. 1 11
  14. 1 12
  15. 2 13
  16. 52
  17. 1 1
  18. 1 2
  19. 1 3
  20. 1 4
  21. 1 5
  22. 1 6
  23. 1 7
  24. 1 8
  25. 1 9
  26. 1 10
  27. 1 11
  28. 1 12
  29. 1 13
  30. 2 1
  31. 2 2
  32. 2 3
  33. 2 4
  34. 2 5
  35. 2 6
  36. 2 7
  37. 2 8
  38. 2 9
  39. 2 10
  40. 2 11
  41. 2 12
  42. 2 13
  43. 3 1
  44. 3 2
  45. 3 3
  46. 3 4
  47. 3 5
  48. 3 6
  49. 3 7
  50. 3 8
  51. 3 9
  52. 3 10
  53. 3 11
  54. 3 12
  55. 3 13
  56. 4 1
  57. 4 2
  58. 4 3
  59. 4 4
  60. 4 5
  61. 4 6
  62. 4 7
  63. 4 8
  64. 4 9
  65. 4 10
  66. 4 11
  67. 4 12
  68. 4 13

样例输出

  1. 0
  2. 1

AC代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. int cnt[5][14];
  7. int check()
  8. {
  9. int ret = 0x7FFFFFFF;
  10. int i, j;
  11. for (i = 1; i <= 4; i++)
  12. for (j = 1; j <= 13; j++)
  13. {
  14. if (cnt[i][j] < ret)ret = cnt[i][j];
  15. }
  16. return ret;
  17. }
  18. int main()
  19. {
  20. int T, n;
  21. int pat, pid;
  22. scanf("%d", &T);
  23. while (T--)
  24. {
  25. memset(cnt, 0, sizeof(cnt));
  26. scanf("%d", &n);
  27. while (n--)
  28. {
  29. scanf("%d%d", &pat, &pid);
  30. cnt[pat][pid]++;
  31. }
  32. printf("%d\n", check());
  33. }
  34. return 0;
  35. }

作答提示

散列表计数。凑扑克牌是木桶(短板)原理,数量最少的花色+牌面的数量就是答案。

H 多项式求导

题目大意

给一个多项式,求其导函数。

输入输出格式参考样例,一次项和零次项均严格按照格式给出。

输出的时候首项如果是正的不要有 + 号。

样例输入

  1. 4*x^4-3*x^2+5*x^1+2*x^0

样例输出

  1. 16*x^3-6*x^1+5*x^0

AC代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. typedef struct Elem
  7. {
  8. int k, p;
  9. }Elem;
  10. Elem F[105];
  11. int mxp;
  12. Elem mkelm(int kk, int pp)
  13. {
  14. Elem ret;
  15. ret.k = kk, ret.p = pp;
  16. return ret;
  17. }
  18. int main()
  19. {
  20. int k, p, i;
  21. int flg = 0;
  22. while (scanf("%d*x^%d", &k, &p) == 2)
  23. {
  24. Elem fx = mkelm(k, p);
  25. if (k == 0 || p == 0)continue;
  26. if (p > mxp) mxp = p;
  27. if (F[p].p == 0)F[p].p = p;
  28. F[p].k += fx.k;
  29. }
  30. for (i = mxp; i > 0; i--)//f'
  31. {
  32. Elem fi = F[i];
  33. if (F[i].p != i)continue;
  34. fi.k *= fi.p, fi.p--;
  35. if (fi.k)
  36. printf("%s%d*x^%d", flg && fi.k > 0 ? "+" : "", fi.k, fi.p), flg = 1;
  37. }
  38. if (!flg)
  39. printf("0");
  40. return 0;
  41. }

作答提示

就是注意输入的时候用 scanf 控制好格式(每一项的格式为 %d*x^%d ),然后注意一下可能有合并同类项(样例是我现编的,我懒得编那种需要合并的数据了)。输出的时候也是控制好格式就行了。

多项式的题平时上机和练习赛练过两次,主要还是考察 scanf 的格式化输入。

I 高精度减法

题目大意

输入俩超大整数( ),可能有前导零不保证 。输出它们的差。

样例输入

  1. 1000
  2. 999

样例输出

  1. 1

AC代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. char s1[505], s2[505];
  7. int a[505], b[505];
  8. int res[505];
  9. int l1, l2, l;
  10. int numcmp()
  11. {
  12. int i;
  13. if (l1 > l2)return 1;
  14. else if (l1 < l2)return -1;
  15. else
  16. {
  17. for (i = l1; i >= 0; i--)
  18. {
  19. if (a[i] > b[i])return 1;
  20. else if (a[i] < b[i])return -1;
  21. }
  22. }
  23. return 0;
  24. }
  25. int hgint_minus(int *r, int *A, int l1, int *B, int l2)//A - B
  26. {
  27. int l = l1 > l2 ? l1 : l2;
  28. int i;
  29. for (i = 0; i < l; i++)
  30. {
  31. r[i] += A[i] - B[i];
  32. while (r[i] < 0)
  33. r[i] += 10, r[i+1]--;
  34. }
  35. while (r[l-1] == 0)l--;
  36. return l;
  37. }
  38. int main()
  39. {
  40. int i;
  41. int flg = 0;
  42. scanf("%s%s", s1, s2);
  43. l1 = strlen(s1), l2 = strlen(s2);
  44. for (i = 0; i < l1; i++)
  45. a[i] = s1[l1 - i - 1] - '0';
  46. for (i = 0; i < l2; i++)
  47. b[i] = s2[l2 - i - 1] - '0';
  48. while (a[l1 - 1] == 0)l1--;
  49. while (b[l2 - 1] == 0)l2--;
  50. flg = numcmp();
  51. if (flg == 0)
  52. l = 1;
  53. else if (flg == 1)
  54. {
  55. l = hgint_minus(res, a, l1, b, l2);
  56. }
  57. else
  58. {
  59. l = hgint_minus(res, b, l2, a, l1);
  60. }
  61. if (flg == -1)printf("-");
  62. for (i = l - 1; i >= 0; i--)
  63. printf("%d", res[i]);
  64. return 0;
  65. }

作答提示

高精度模板题,没任何思维难度,倒序存储然后模拟竖式从个位开始算,然后注意借位。

别忘了先比较大小,以及过滤前导零

这种题直接准备好板子带到考场上抄就行了。

J 2的次幂表示

题目大意

此题为洛谷原题(P1010)。访问链接:https://www.luogu.org/problem/P1010

样例输入

  1. 137

样例输出

  1. 2(2(2)+2+2(0))+2(2+2(0))+2(0)

AC代码

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <math.h>
  4. #include <string.h>
  5. #include <ctype.h>
  6. void solve(int n)
  7. {
  8. int i = 15;
  9. int flg = 0;
  10. while (i >= 0)
  11. {
  12. int base = (1 << i);
  13. if (n & base)
  14. {
  15. switch(i)
  16. {
  17. case 2:
  18. printf("%s2(2)", flg ? "+" : ""), flg = 1;
  19. break;
  20. case 1:
  21. printf("%s2",flg ? "+" : ""), flg = 1;
  22. break;
  23. case 0:
  24. printf("%s2(0)",flg ? "+" : ""), flg = 1;
  25. break;
  26. default:
  27. printf("%s2(", flg ? "+" : ""),flg = 1;
  28. solve(i);
  29. printf(")");
  30. }
  31. }
  32. i--;
  33. }
  34. }
  35. int main()
  36. {
  37. int n;
  38. scanf("%d", &n);
  39. solve(n);
  40. return 0;
  41. }

作答提示

递归。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注