[关闭]
@Chobi15 2015-07-17T12:55:44.000000Z 字数 4639 阅读 1352

第一讲 程序设计基础

程序的构成

  1. 只要会循环和判断,就会编程了!
  2. 关于函数?
    将统一的操作封装到一起,方便使用
  3. 关于数组和指针?
    对数据的存储操作
  4. 关于输入输出?
    由硬件提供简单的指令

  5. 程序的主要意义:
    通过大量的重复执行某些指令,能够快速得到人力无法在有生之年得出的结果。

    1. 从上亿条信息中,找出规律:“买婴儿尿布的人多半会买啤酒”。
    2. 判断2^57885161 - 1是否为素数。
    3. 使用“必胜策略”下五子棋

程序的编写过程

ACM竞赛中涉及的输入方式

竞赛中使用的输入方法

输入结束方式

竞赛中使用的输出方法

字符串的使用

字符串的读入:scanf , gets , fgets.

常用字符串函数

strlen(测量字符串长度)
strstr(一个字符串中搜索另一个字符串)
strcmp(字符串比较)
strcpy与strncpy(字符串的复制)
sscanf与sprintf(从字符串格式化读入,向字符串格式化写入)
memset 这是一个内存初始化函数,初始化字符串可用初始值只能为0 和 -1

  1. memset(str,0, sizeof(str));

atoi, itoa, atof, atol,禁用!!!!!

高精度计算

为什么要使用高精度?

计算下面这个结果:

32767+32767

计算下面这个结果:

327673276732767+327673276732767

计算下面这个结果:

327673276732767327673276732767 + 327673276732767327673276732767

整数(int)数据范围为-2^32~2^32-1,长整数(long long)数据范围为-2^64~2^64-1,如果十进数超过20位就不能胜任了。这时就要用到高精度数的运算了。

高精度储存

int w[100];一般为w[0]存储该数的位数,w[1]存个位,w[2]存十位,….
如整数“120”,按高精度数存储:w[0]=3;w[1]=0;w[2]=2;w[3]=1。
注意这里是倒着保存数的。这样做的目的在于进行运算时方便数位对齐。
但由于是高精度数的运算可以多次用到,所以我们定义成函数形式方便使用。为了让函数能直接返回值,所以可以定义成结构体。

  1. struct hp
  2. {
  3. int w[10005];// w[0]用于存储这个数的位数
  4. };

高精度计算

1. 加法

高精度数相加实际上就是模拟我们自己计算加法的过程。
步骤 1.对应位相加 2.进位.高精度加法类似

  1. hp jia(hp a, hp b)
  2. {
  3. hp c;
  4. memset(c.w, 0, sizeof(c.w)); //将c.w里所有数清0.
  5. c.w[0] = a.w[0] > b.w[0] ? a.w[0] : b.w[0];//初步估算位数
  6. for(int i = 1; i <= c.w[0]; i++){
  7. c.w[i] = a.w[i]+b.w[i]; //对应位相加
  8. }
  9. for(int i = 1; i <= c.w[0]; i++){
  10. if(c.w[i] >= 10){
  11. c.w[i] %= 10;
  12. c.w[i+1] += 1; //进位
  13. }
  14. }
  15. if(c.w[c.w[0]+1] != 0)c.w[0]++;
  16. return c;
  17. }

2. 乘法

高精度乘法也是模拟计算乘法
步骤 1.对应位相乘 2.进位

  1. hp cheng(hp a, hp b)
  2. {
  3. hp c;
  4. memset(c.w, 0, sizeof(c.w)); //将c.w里所有数清0.
  5. c.w[0] = a.w[0] + b.w[0] - 1; //初步估算结果的位数
  6. for(int i = 1; i <= a.w[0]; i++){
  7. for(int j = 1; j <= b.w[0]; j++){
  8. c.w[i+j-1] += a.w[i] * b.w[j]; //每一位相乘
  9. }
  10. }
  11. for(int i = 1; i <= c.w[0]; i++){
  12. if(c.w[i] >= 10){
  13. c.w[i+1] += c.w[i] / 10;
  14. c.w[i] %= 10;
  15. }
  16. }
  17. if(c.w[c.w[0]+1] != 0)c.w[0]++; // 计算精确位数
  18. return c;
  19. }

高精度的输出

高精度的输出方式为从最高位输出到最低位

  1. void print(hp c)
  2. {
  3. for(int i = c.w[0]; i >= 1; i--){ //输出
  4. printf("%d", c.w[i]);
  5. }
  6. printf("\n");
  7. }

高精度的输入

因为高精度的数已经不能用int 和 long long来储存.所以自然也不能用scanf("%d%lld")来输入.
输入方法为:
1. 将高精度数储存到字符串中
2. 把字符串转化为 struct hp 变量,用于之后的计算

输入数据 123456789123456789

  1. hp input()
  2. {
  3. hp a;
  4. memset(a.w, 0, sizeof(a.w))
  5. char str[100];
  6. scanf("%s", str); //将数字用数组保存
  7. int len = strlen(str);
  8. a.w[0] = len;
  9. for(int i = len-1; i >= 0; i--){
  10. a.w[len- i] = str[i] - '0'; //通过位置关系构建高精度数.
  11. }
  12. return a;
  13. }

第一章的内容就讲完啦.来,完成我们的第一题!!
Bull Math
Input

输入包括两行 每一行是一个不超过40位的数字

Output

输出这两个数的乘积

代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. struct hp
  4. {
  5. int w[100];
  6. };
  7. hp cheng(hp a, hp b)
  8. {
  9. hp c;
  10. memset(c.w, 0, sizeof(c.w)); //将c.w里所有数清0.
  11. c.w[0] = a.w[0] + b.w[0] - 1; //初步估算结果的位数
  12. for(int i = 1; i <= a.w[0]; i++){
  13. for(int j = 1; j <= b.w[0]; j++){
  14. c.w[i+j-1] += a.w[i] * b.w[j]; //每一位相乘
  15. }
  16. }
  17. for(int i = 1; i <= c.w[0]; i++){
  18. if(c.w[i] >= 10){
  19. c.w[i+1] += c.w[i] / 10;
  20. c.w[i] %= 10;
  21. }
  22. }
  23. if(c.w[c.w[0]+1] != 0)c.w[0]++; // 计算精确位数
  24. return c;
  25. }
  26. void print(hp c)
  27. {
  28. for(int i = c.w[0]; i >= 1; i--){ //输出
  29. printf("%d", c.w[i]);
  30. }
  31. printf("\n");
  32. }
  33. hp input()
  34. {
  35. hp a;
  36. memset(a.w, 0 ,sizeof(a.w));
  37. char str[100];
  38. scanf("%s", str);
  39. int len = strlen(str);
  40. a.w[0] = len;
  41. for(int i = len-1; i >= 0; i--){
  42. a.w[len- i] = str[i] - '0';
  43. }
  44. return a;
  45. }
  46. int main()
  47. {
  48. hp a, b;
  49. a = input(); // 输入a
  50. b = input(); // 输入b
  51. hp c = cheng(a, b); // 计算 a * b
  52. print(c); //输出结果c
  53. return 0;
  54. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注