GNK DEVc++

02. C++导言.软件

主讲老师 - 姚俞坚

1. 导言须知

  • 课程方向:

    • 知识点主要面向小学**6年级+**的少儿编程 C++ 课程,适用于信奥赛选拔;

    • 课程比较适合理工科父母的亲子互动,教培机构老师的备课参考

    • 特别注意①:C++ 课程 只有启蒙这一套是 小学阶段适合,后续全部中学;

    • 特别注意②:C++ 课程 仅有本套课程 理工科家长还能亲子,后续只推荐教培老师学习;

    • 特别注意③:虽然是 C++ 编程课程,但和 C++ 几乎没有关系,如何理解?

      • 很多学习者在学习时,找那种职业成人的C++课程,咨询学了是否可以打比赛?
      • 你学习的是信息学奥林匹克竞赛之启蒙阶段,只不过用了官方推荐的 C++ 环境罢了;
      • 如果官方推荐了别的编程环境,学习的内容区别不大,用不到 C++ 自身的特性;
      • 比如 C++ 可以做嵌入式开发、客户端服务端开发、音频视频开发、大型游戏开发等;
      • 上面所说的东西,都不会学到,根本用不到 C++ 的各种能力。
      • 而我们学习的是通过 C++ 编程环境,去解决计算机思维运算下的数理逻辑题罢了。
      • 总结:我们的目的是 **答题 **,不是做 **开发 **。说白了就是 数学应用题考试
  • 知识点规划:

    • 启蒙阶段(本套):

      • 语法基础、分支、循环、数组、函数、字符串、结构体;
      • 其中函数的递归详解或深入、数组中的排序算法、字符串的进制、编码、位运算不包含;
    • 后续阶段(非本套):

      • 过渡篇:进制转换、编码、位运算、暴力枚举、高精度等;
      • 排序篇:冒泡、插入、选择、快速等;
      • 算法篇:递归、递推、模拟、分治、二分、贪心、倍增等;
      • 搜索篇:深度优先DFS、广度优先BFS等;
      • 数据结构篇:链表、队列、栈、二叉树、并查集等;
      • 图论篇:最小生成树、最短路等;
      • 动态规划篇:背包DP等;
    • 详情参考:

      • 上面只列出了大概知识点,详情参考:学习路线 - OI Wiki (oi-wiki.org)
      • 一般培训机构,大概率只会做到 CSP-J/S 入门级的比赛,难度尚可;
      • 更高级的比如 NOIP同等更高本人没教过,能力不够,教不了!!!
    • 我会做到哪?

      • 不清楚。。。本来只想做到小学1-6年级。这套做完就全部完结;
      • 但。。。不多做点浑身难受;
      • 如果。。。突然断了,说明难度太大,我跑路了。。。。
  • 第一个C++程序:

    #include <iostream>
    using namespace std;
    
    int main() 
    {
    	cout << "我的第一个C++程序!"; 
    	return 0;
    }
    
  • 程序详解:

    • 真正需要理解的就一行:cout << “我的第一个C++程序!”;

      • cout 表示 输出,直白点:运行程序后在窗口显示后面双引号里面的内容;
      • << 表示 插入运算符,语法表示:在 cout 和 后面输出内容,需要用这个+空格隔开;
      • ; 表示语句结束,一条输出语句写完后,需要通过分号表示结束;
    • 其余的代码部分,全员基本格式,无须理解,做成模板自动即可;

      • 虽说无须理解,但还是象征性的解释一下:
        • include:头文件,导入外部库;iostream 表示支持输入输出;
        • using…:命名空间,防止冲突;
        • int main:主函数,程序会从这里执行;
        • return 0:返回0,表示程序在这里结束;
      image-20231116160236858

03. 变量存储.注释

主讲老师 - 姚俞坚

1. 变量声明

  • 什么是变量?变量就是一个可以存储东西的存储罐,具体特性如下:

    • 每次存储罐里只能存一次东西,也就是说再次存储时,上一次存储的东西会被替换掉;
    • 声明变量就好比你拿出了一个存储罐,实际上是在内存里开辟了一个空间;
    • 不管是现实中的存储罐还是内存开一个空间,多了防止混淆就需要贴个标签,命个名
    • 我们来通过一张图来理解一下,这个声明概念:
  • 那么,如何通过编程来实现变量的声明呢?

    // 声明一个变量a,类型是整数
    int a;
    // 注意1:= 不是等于的意思,是赋值的意思
    // 注意2:阅读代码从右边向左边阅读,意为:将数字123赋值给变量a
    a = 123;
    // 输出变量a
    cout << a;
    

2. 命名的规则

  • a=123 的例子中,a是变量名,但变量的名字有什么要求?需要注意哪些规则?能乱起吗?

    • 变量名只能是:a-z、A-Z、0-9以及下划线组成;

    • 变量名第一位不可以是数字;

    • 变量名不可以是 C++ 关键字:比如 int main 之类的;

    • 变量需要定义后才可以使用:int a; a = 123;

    • 变量名区分大小写,A和a不同;

      • abc(合法)、a123(合法)、_xyz(合法)、123a(不合法)
  • 为了让变量名更加的有可读性,比如:你的名字:

    • 第一种经典命名方式,驼峰式:yourName,或YourName,我比较喜欢前者;
    • 第二种经典命名方式:蛇形式:your_name,用的也比较多;
    // 声明一个字符串
    string yourName;
    // 字符串类型,需要双引号包含
    yourName = "你的名字";
    cout << yourName;
    

04. 四则运算.输入

主讲老师 - 姚俞坚

1. 加减乘除

虽说叫做四则运算,但其实运算符往往不止加减乘除这四种:

运算符号格式
+1 + 1
-2 - 1
*3 * 4
/6 / 2
求余%10 % 7
累加++i++
累减i–
  • 在编程语法中乘法 x 用 ***** 号代替,除法 ÷/ 代替。

    // endl 表示换行 Ctrl + D复制一行
    cout << 1 + 1 << endl;
    cout << 3 - 2 << endl;
    cout << 4 * 5 << endl;
    cout << 9 / 7 << endl;
    cout << 7 % 3 << endl;
    

2. cin输入

如果想让用户在键盘输入内容,可以使用 cin 关键字;

// 同时声明两个整型变量
int a,b;
// 输入两个数,并赋值给a和b
// 注意:同时输入a和b时,中间需要用空格键隔开
cin >> a >> b;
// 打印a+b的和
cout << a + b;

05. 学会使用OJ答题

主讲老师 - 姚俞坚

1. OJ系统

所谓的OJ系统,即:用于竞赛编程中,海量刷题的工具系统;

2. 使用洛谷

  • 在首页直接输入题号:B2002,可直接进入题目页面;题号不区分大小写;

  • 或者在右侧,有一个 题单 >> 【入门1】顺序结构 >> 题目列表 >> B2002 Hello,World!

    • 开始读题

    • 在 小熊猫C++ 编写代码,并运行结果

    • 将代码复制,回到答题页,选择 提交答案

    • 选择 C++ 标准 ,最近的就行,提交测评

    • 出现全部都是 绿色AC,表示正确

      #include <iostream>
      using namespace std;
      
      int main() {
      	cout << "Hello,World!";
      	return 0;
      }
      

3. 使用博宜

  • 在首页直接输入题号:1000,可直接进入题目页面;

  • 或者在右上角 题单 >> 官方题单 >> 基本运算 >> 1000;

    • 答题和洛谷一样,不再赘述:

      #include <iostream>
      using namespace std;
      
      int main() {
      	int a,b;
      	// 注意输入的变量 空格隔开
      	cin >> a >> b;
      	// 输出和
      	cout << a + b;
      	return 0;
      }
      

06. 数据类型.转换

主讲老师 - 姚俞坚

1. 数据类型

类型名类型声明解释说明
整型int-2147483648 到 2147483647 的范围的整数
长整形long long比上面大很多很多,这里装不下,具体搜索
字符型char赋值只能是一个字符,比如 ‘A’,必须用单引号,双表示字符串不是字符
浮点型float也叫实型或小数型,38位以内的小数,只保留6为有效数字
  • 其实还有很多类型,暂时先理解这几个,后续用到的再单独讲解;

    // 字符型,切记是单引号
    char ch = 'a';
    // 长整形
    long long b = 100000000000000000;
    // 浮点型,只能六位
    float c = 3.1415926;
    cout << b << endl;
    cout << ch << endl;
    cout << c << endl;
    return 0;
    

2. 类型转换

  • 这里我们只探讨整数和小数之间的转换,其它的放到以后;

  • 类型转换分为两种:隐式转换和强制转换;

    // 两边都是整数,结果也是整数:1
    cout << 8 / 5 << endl;
    // 两边有一边是浮点,结果是浮点:1.6
    cout << 8.0 / 5 << endl;
    // 强制转换浮点,float()是转换函数,将整数转换成浮点数,8叫做参数
    cout << float(8) / 5 << endl;
    // 强制转换整型
    cout << int(3.14 * 5.25) << endl;
    

3. 保留小数点

  • 首先要引入相关库:

  • 其次使用 setprecision(n) 函数 来设置保留小数点的位数;

    // 输出保留的小数点
    // fixed可以在缺少的位数补零,这样就精确保证2位
    cout << fixed << setprecision(2) << 3.1415926;
    

07. 1599.米老鼠偷糖果

主讲老师 - 姚俞坚

1. 代码详解

// 声明三个整型变量
int n, a, x;
// 输入三个数并赋值
cin >> n >> a >> x;
// 计算
cout << n - x * a;

08. 1323.扩建花圃问题

主讲老师 - 姚俞坚

1. 代码详解

// 三个整型变量
int m, n, s;
// 输入
cin >> m >> n >> s;
// 求出高度
int h = s / n;
// 计算
cout << m * h;

09. P1425.小鱼的游泳时间

主讲老师 - 姚俞坚

1. 代码详解

// 5个整数
int a, b, c, d, e;
// 输入
cin >> a >> b >> c >> d;
// 全部转换到分钟,然后 第二段时间 - 第一段时间
e = (c * 60 + d) - (a * 60 + b);
// 计算
cout << e / 60 << " " << e % 60;

10. 1598.文具店的折扣

主讲老师 - 姚俞坚

1. 代码详解

// 三个整数
int x, y, n;
float a;
cin >> x >> y >> n;
// 总 - 计算用了多少钱
a = n - (x * 1 + y * 1) * 0.9;
// 输出,并保留1位
cout << fixed << setprecision(1) << a;

11. P5706.再分肥宅水

主讲老师 - 姚俞坚

1. 代码详解

// t毫升
float t;
// n同学
int n;
// 输入
cin >> t >> n;

// 每个人分得多少毫升,保留三位
cout << fixed << setprecision(3) << t / n << endl;
// 一共需要多少杯子
cout << n * 2 << endl;

12. 1345.玫瑰花圃

主讲老师 - 姚俞坚

1. 代码详解

// 花圃网格行列数
float n, total, pink;
cin >> n;

// 有多少块
total = n * n;

// 粉色数量, 中间一行一列为:n + n - 1 + 4 (四边)
pink = n + n + 3;

// 求比例
cout << fixed << setprecision(1) << pink / total * 100;
// 输出百分号
cout << "%";

13. P3954.NOIP2017普及组.成绩

主讲老师 - 姚俞坚

1. 代码详解

// 三项成绩
int a, b, c;
// 输入
cin >> a >> b >> c;
// 计算
cout << a * 0.2 + b *0.3 + c * 0.5;

14. 1029.倒序输出一个四位整数

主讲老师 - 姚俞坚

1. 代码详解

// 输入一个四位整数
int a, qian, bai, shi, ge;
cin >> a;

// 拆位
qian = a / 1000;
bai  = a / 100 % 10;
shi  = a / 10 % 10;
ge   = a % 10;

// 倒序
// 这里有一个问题:如果 cout <<  ge << shi << bai << qian;
// 会有一个测试点无法通过;因为第二个样例中,1600,会去掉零,所以需要通过加整,而不是连整;
cout << ge * 1000 + shi * 100 + bai * 10 + qian;

15. 输入输出.格式化

主讲老师 - 姚俞坚

1. 输出

对于格式化输出,本节课将学习两个函数 scanf()printf() 来取代之前的cin和cout方法;

  • 假如,我们要输出一组运算等式:1 + 2 = 3,而1是变量a,2是变量b,3是a+b的运算结果;
int a = 1, b = 2;
// cout
cout << a << " + " << b << " = " << a + b;

cout << endl;

// printf
printf("%d + %d = %d", a, b, a + b);
  • printf() 函数极其方便的原因,它可以先按照自己的输出格式,先写出来,不需要头脑翻译;

  • 然后把需要替换成变量的部分,用 %d 来表示即可,而后续对应的位置换成变量或表达式运算即可;

  • %d 这里表示占位的内容 是 整型,也有各种其它的占位符,这里罗列出常用的几个:

    占位控制符说明
    %d整数
    %f浮点数(float)
    %c字符
    %s字符串
  • 最终的语法结构如下:

    printf(格式控制符, 占位替换列表)
    

2. 输入

  • 从上面例子中,我们使用 scanf() 函数来控制输入:

    int a, b;
    // scanf
    scanf("%d %d", &a, &b);
    
    // printf
    printf("%d + %d = %d", a, b, a + b);
    
  • 先了解下输入参数的格式需求:

    scanf(格式控制符, 地址集)
    
  • 暂时没有办法解释这个地址是什么意思?举个并不恰当但好理解的说明:

    • 快递员给张三寄快递,直接送到张三手上;这是 cin
    • 快递员给张三家地址寄快递,不管是凤巢、门卫代收还是家人收件,最终会交给张三;这是 scanf()
    • 所以,a表示张三,&a表示张三家的地址;而sacanf() 参数要求是地址,故在变量前加&;
    • 而这个知识点叫做 引用,是比较靠后的知识点,暂时不用理解;
    • 后续,自然也会有 变量本身就是引用,反而参数不需要 & 符号;

3. 格式化

  • 在使用 printf() 时,我们需要输出各种特殊字符,比如百分号,换行,以及场宽精度问题等:

    符号说明和示例
    \\输出一个斜杠,printf(“\\”);
    \n换行,printf(“\n”);
    %%百分号,printf(“%”);
    数字场宽,printf(“%3d%5d”);
    小数精度,printf(“%.2f”, 3.1415926);
    // 格式化
    printf("%%\\\n");
    
    // 场宽
    printf("%3d%5d\n", a, b);
    
    // 精度
    printf("%.2f\n", 3.1415926);
    // 场宽+精度
    printf("%8.2f", 3.1415926);
    

16. P5705.数字反转

主讲老师 - 姚俞坚

1. 代码详解

// 输入一个浮点数,只有一位小数
float a;
int b, qian, bai, shi, ge;
scanf("%f", &a);

// 各个位进位
b = a * 10;

// 拆位
qian = b / 1000;
bai  = b / 100 % 10;
shi  = b / 10 % 10;
ge   = b % 10;

// 合并输出
printf("%d.%d%d%d", ge, shi, bai, qian);

17. 1109.加密四位数

主讲老师 - 姚俞坚

1. 代码详解

// 四位整数
int a, qian, bai, shi, ge;
cin >> a;

// 拆位
qian = ((a / 1000) + 5) % 10 ;
bai  = ((a / 100 % 10) + 5) % 10;
shi  = ((a / 10 % 10) + 5) % 10;
ge   = ((a % 10) + 5) % 10;

// 输出倒序,本题没有要求必须是整型去零,所以,直接拼装可过
printf("%d%d%d%d", ge, shi, bai, qian);

18. 运算符表达式.布尔

主讲老师 - 姚俞坚

1. 关系运算符

布尔类型的值,是专门用于各种表达式的判断,只存在两种值:

// 布尔类型,只有两种值:true和false
// true 表示成立, false 表示不成立
// true 输出为1, false 输出为 0
bool a = true;
bool b = false;

cout << a << endl;
cout << b << endl;
  • 除了直接赋值为 true 或 false,也可以通过关系运算符来返回布尔值的数据:
名称关系运算符表达式返回值
大于>成立返回 true(6 > 5),否则为 false(6 > 7)
小于<成立返回 true(6 < 8),否则为 false(6 < 5)
等于==成立返回 true(6 == 6),否则为 false(6 == 7)
大于等于>=成立返回 true(7 >= 6),否则为 false(7 >= 8)
小于等于<=成立返回 true(6 <= 6),否则为 false(6 <= 5)
不等于!=成立返回 true(6 != 5),否则为 false(6 != 6)
// 返回 true(1) 和 false(0)
cout << (6 > 5) << endl;
cout << (6 > 7) << endl;
cout << (6 < 7) << endl;
cout << (6 == 6) << endl;
cout << (6 == 7) << endl;
cout << (6 >= 4) << endl;
cout << (6 != 6) << endl;
cout << (6 != 5) << endl;

2. 逻辑运算符

除了关系运算符之外,还有一种叫做逻辑运算符,具体如下:

名称逻辑运算符表达式返回值
&&x && y表示and,x 和 y 同时为 true 时,返回 true,否则返回 false
||x || y表示or, x 和 y 只要其中之一为 true,返回 true,否则返回 false
!!x表示not, x 为 true 时,结果为 false,否则为 true
# 逻辑运算符
cout << (5 > 6 && 5 > 4) << endl;
cout << (7 > 6 && 5 > 4) << endl;
cout << (5 > 6 || 5 > 4) << endl;
cout << (5 > 6 || 5 < 4) << endl;
cout << !(5 > 6) << endl;
cout << !true << endl;

19. B2019.整型与布尔型的转换

主讲老师 - 姚俞坚

1. 代码详解

int a;
bool flag;

// 赋值
cin >> a;
flag = a;
a = flag;

// 输出
cout << a;

// 规则说明
// 注意1:布尔值true(成立) 输出1,false(不成立) 输出0
// 注意2:数值中,非零即为true,0为false
// 下面中,5和-5转换成布尔值均为true
//cout << bool(5)  << endl;
//cout << bool(-5) << endl;

20. B2040.判断是否为两位数

主讲老师 - 姚俞坚

1. 代码详解

int a;
bool flag;

// 输入
cin >> a;

// 赋值
// 条件1:a >= 10
// 条件2:a <= 99
// 整合:a >= 10 && a <= 99
// 看花眼的话,可以加个括号增加可读性
// 括号加法1:(a >= 10 && a <= 99)
// 括号加法2:((a >= 10) && (a <= 99))
flag = ((a >= 10) && (a <= 99));

// 输出
cout << flag;

21. B2041.收集瓶盖赢大奖

主讲老师 - 姚俞坚

1. 代码详解

int a,b;

// 输入
cin >> a >> b;

// 判断,|| 或者,只要成立一个即可
cout << (a >= 10 || b >= 20);

22. 分支语句.条件判断

主讲老师 - 姚俞坚

1. if…单一条件

假设你一周七天中只有周一才能穿新衣服,那么就需要 if语句单一条件判断

满足条件
未满足条件
程序开始
输入星期几
判断是否星期一
穿上新衣
程序结束
  • 单一条件判断的if语句格式如下:

    // 第一个花括号放在第一行末,或第二行开头均可,执行语句需要缩进一个Tab键
    if (条件表达式) {
        条件成立执行这里;
    }
    
    // 注意1:如果成立后的语句只有一句,可以去掉花括号,或放在第一行末
    if (条件表达式) 条件成立执行这里;
    
    // 或
    if (条件表达式) 
        条件成立执行这里;
    
    int flag;
    cin >> flag;
    
    // flag == 1 返回布尔值,成立的话执行缩进的第一行语句
    // 如果有缩进的第二行,且没有括号包含,则无效
    if (flag == 1) 
        cout << "周一穿新衣!";
    

2. if…else分支

单一if语句比较高冷,如果未满足条件,ta就不理你了;而else分支则可爱许多;

满足条件
未满足条件
程序开始
输入星期几
判断是否星期一
穿上新衣
程序结束
不穿新衣
  • else分支条件判断的if语句格式如下:
if (条件表达式) {
    条件成立执行这里;
} else {
	条件不成立执行这里;
}
// 单行语句
if (flag == 1) 
	cout << "周一穿新衣!";
else
	cout << "没有新衣穿!";

// 多行语句
if (flag == 1) {
    cout << "嘿嘿!";
    cout << "周一穿新衣!";
} else {
    cout << "哎!";
    cout << "没有新衣穿!";
}

23. 1632.需要几辆车

主讲老师 - 姚俞坚

1. 代码详解

int n, a;
cin >> n;

// 判断人数是否刚好30人
if (n % 30 == 0) 
    a = n / 30;
else
    // 31人 = 1 + 1 = 2辆
    // 65人 = 2 + 1 = 3辆
    a = n / 30 + 1;

// 输出
cout << a;
return 0;

24. 1630.打电话

主讲老师 - 姚俞坚

1. 代码详解

int n;
float sum;

// 输入
scanf("%d", &n);

// 计算
if (n >= 10)
    sum = n * 1.2;
else
    sum = n * 1.5;

// 格式化,保留小数1
printf("%.1f", sum);

25. 1045.能否构成三角形

主讲老师 - 姚俞坚

1. 代码详解

int a, b, c;
cin >> a >> b >> c;

// 判断三角形
if (a + b > c && a + c > b && b + c > a)
    cout << "Yes";
else
    cout << "No";
return 0;

26. 1659.是否含有数字5

主讲老师 - 姚俞坚

1. 代码详解

int n, a, b, c, d, e;
cin >> n;

// 拆位
a = n / 10000;
b = n / 1000 % 10;
c = n / 100 % 10;
d = n / 10 % 10;
e = n % 10;

// 判断 输出
if (a == 5 || b == 5 || c == 5 || d == 5 || e == 5)
    cout << a + b + c + d + e;
else
    cout << n;

27. 1718. 闯关大冒险?

主讲老师 - 姚俞坚

1. 代码详解

#include <iostream>
using namespace std;

int main() {
	int n, a, b, c, d, maxn;
	cin >> n;
	
	// 拆位
	a = n / 1000;
	b = n / 100 % 10;
	c = n / 10 % 10;
	d = n % 10;
	
	// 求最大值,初始值比规定的小即可,四位数的话最小是0,-1即可
	maxn = -1;
	
	// a
	if (a > maxn)
		maxn = a;
	//b
	if (b > maxn)
		maxn = b;
	//c
	if (c > maxn)
		maxn = c;
	//d
	if (d > maxn)
		maxn = d;
	
	// 输出
	cout << maxn;
	
	return 0;
}

28. P5709.Apples Prologue

主讲老师 - 姚俞坚

1. 代码详解

int m,t,s,total,re;
cin >> m >> t >> s;

// 总分钟 = m个数 x t分钟 = 50 x 10 = 500分钟
total = m * t;
// 剩余个数 = (总分数total - 已过分数s) / t分钟 = (500 - 200) / 10 = 30
re = (total - s) / t;

//问题:假设有一个测试点是不能被整除的时间,s 是 222
// (500 - 222) / 10 = 27余8,剩下的完整个数是27,所以无需+1 -1操作
cout << re;
image-20231201112236927
  • 通过了两个测试点,失败了三个测试点:
    • 测试2,没有考虑过神仙吃苹果不需要时间,也就是t为0时,不可以作为被除数;
    • 测试1,3,没有考虑过s时间特别大,比如10000,导致产生负数个数;
int m,t,s,total,re;
cin >> m >> t >> s;

// 特例1,神仙吃苹果,t是0分钟吃一个,t会当作被除数导致错误
if (t == 0) {
    cout << 0;
    return 0;		// 退出程序,不再往下执行
}


// 总分钟 = m个数 x t分钟 = 50 x 10 = 500分钟
total = m * t;
// 剩余个数 = (总分数total - 已过分数s) / t分钟 = (500 - 200) / 10 = 30
// 问题:假设有一个测试点是不能被整除的时间,s 是 222
// (500 - 222) / 10 = 27余8,剩下的完整个数是27,余数不完整,忽略

// 特例2,假设s时间非常大,有10000
if (total < s) {
    cout << 0;
    return 0;		// 退出程序,不再往下执行
}

re = (total - s) / t;


cout << re;
image-20231201114056201

29. 多重判断.嵌套判断

主讲老师 - 姚俞坚

1. else if…分支

很多时候的分支判断,可能不止一条或两条,此时就需要使用 else if 多重分支结构

if (表达式成立) {
    执行语句;
} else if (表达式成立) {
    执行语句;
} else if (表达式成立) {
    执行语句;
} else if (表达式成立) {
    执行语句;
} else {
    执行语句;
}
// 8岁之前:成长阶段
// 8-25之间:求学阶段
// 26-60之间:工作阶段
// 大于60:退休阶段

int a;
cin >> a;

// 多重循环
if (a < 8) {
    cout << "成长阶段";
} else if (a >= 8 && a <= 25) {
    cout << "求学阶段";
} else if (a >= 26 && a <= 60) {
    cout << "工作阶段";
} else {
    cout << "退休阶段";
}

2. 嵌套判断

在某一个成立的条件下,是否还有不同的另外的条件判断呢,此时需要用到嵌套判断

} else {
    cout << "退休阶段,请输入孙子孙女数量:";
    // 如果退休阶段有很多个孙子孙女,那还是需要打工赚压岁钱的
    int b;
    cin >> b;
    if (b >= 7 && b <=9) {
        cout << "无法退休,要打两份工";
    } else if (b >=3 && b <= 6) {
        cout << "无法退休,要打一份工";
    } else if (b < 3) {
        cout << "退休生活";
    }
}

30. P5715.三位数排序

主讲老师 - 姚俞坚

1. 代码详解

int a,b,c;
cin >> a >> b >> c;

// 多重判断,从小到大排序
// 无非是:abc,acb,bca,bac,cab,cba 这六种
// 输出的值需要空格 a b c 这样;用printf更方便
if (a <= b && a <=c) {
    // a最小
    if (b <= c) 
        printf("%d %d %d", a, b, c);
    else
        printf("%d %d %d", a, c, b);
} else if (b <= a && b <= c) {
    // b最小
    if (a <= c)
        printf("%d %d %d", b, a, c);
    else
        printf("%d %d %d", b, c, a);
} else if (c <= a && c <= b) {
    // c最小
    if (a <= b)
        printf("%d %d %d", c, a, b);
    else
        printf("%d %d %d", c, b, a);
}

31. 1667.最大和最小数的差

主讲老师 - 姚俞坚

1. 代码详解

int n, a, b, c, maxn, minn;
cin >> n;

// 拆位
a = n / 100;
b = n / 10 % 10;
c = n % 10;

// 求最大值
maxn = -1;
if (a >= b && a >= c) {
    maxn = a;
} else if (b >= c) {
    maxn = b;
} else {
    maxn = c;
}

// 求最小值
minn = 10;
if (a <= b && a <= c) {
    minn = a;
} else if (b <= c) {
    minn = b;
} else {
    minn = c;
}

// 差
cout << maxn - minn;

32. 1310.至少要买几瓶止咳糖浆?

主讲老师 - 姚俞坚

1. 代码详解

// 花花年龄,需要的总毫升数,需要的瓶数
int n, sum, t;
cin >> n;

// 判断
if (n > 10) {
    // 5天 x 每次毫升25 x 一日3次
    sum = 5 * 25 * 3; 
} else if (n >= 7 && n <= 10) {
    sum = 5 * 15 * 3;
} else if (n >= 3 && n <= 6) {
    sum = 5 * 5 * 3;
}

// 求出需要几瓶
if (sum % 120 == 0) {
    t = sum / 120;
} else {
    t = sum / 120 + 1;
}

cout << t;

33. P1422.小玉家的电费

主讲老师 - 姚俞坚

1. 代码详解

// 电费量
int n;
// 电费
float sum;
cin >> n;

// 判断
if (n >= 401) {
    // 150 度的花费
    sum = 150 * 0.4463;
    // 250 度的花费
    sum = sum + (400 - 150) * 0.4663;
    // 400 度的花费
    sum = sum + (n - 400) * 0.5663;
} else if (n >= 150 && n <= 400) {
    // 150 及以内的花费
    sum = 150 * 0.4463;
    // 150 - 400 之间的花费
    sum = sum + (n - 150) * 0.4663;
} else {
    sum = n * 0.4463;
}

// 输出
printf("%.1f", sum);

34. P1424.小鱼的航程(改进版)

主讲老师 - 姚俞坚

1. 代码详解

// 从周x开始,经过n天,总公里数
int x, n, sum;
cin >> x >> n;

// 一周7天:1 2 3 4 5 6 7
// 样例数据: 10天 从周3开始,双休,8天:250 x 8 = 2000
// 思路:过滤掉双休即可

// 判断n是不是整周,比如:7 14 21,re表示剩余的天数
int re = n % 7;

// 获取全周游泳总天数
int wd = n / 7 * 5;

// 判断思路解析
// 假设从周1开始,经过7或14天,直接:wd * 250
// 假设从周3开始,经过10天,最后一周到周5,无须减双休:(wd + re) * 250
// 假设从周3开始,经过11天,最后一周到周6,需要减1天:(wd + re - 1) * 250
// 假设从周3开始,经过12天,最后一周到周日,需要减2天:(wd + re - 2) * 250

// 有剩余天数
if (re != 0) {
    // 情况1:如果一开始就是从周日开始 x == 7,这一天直接减掉-1
    // 情况2:如果最后一周到了周六 re + x == 7,这一天也需要-1
    if (x == 7 || re + x == 7) {
        sum = (wd + re - 1) * 250;
        // 情况3:一开始从周六开始,最后一周剩余re+x等于8,表示周日 -2
    } else if (x == 6 || re + x == 8) {
        sum = (wd + re - 2) * 250;
    } else {
        sum = (wd + re) * 250;
    }
} else {
    // 没有剩余天数,直接算:7 / 7 x 5 = 5天 或 14 / 7 x 5 = 10天
    sum = wd * 250;
}

// 输出
cout << sum;

35. P1909.NOIP2016.普及组.买铅笔

主讲老师 - 姚俞坚

1. 代码详解

// 数据变量
int n, a1, a2, b1, b2, c1, c2;
// 计算变量
int s1, s2, s3;

// 录入数据
cin >> n;
cin >> a1 >> a2;
cin >> b1 >> b2;
cin >> c1 >> c2;

// 题目描述已经说出规则
// 57 / 2 = 28...1

// 方案1
if (n % a1 == 0) s1 = n / a1 * a2;
else s1 = (n / a1 + 1) * a2;

// 方案2
if (n % b1 == 0) s2 = n / b1 * b2;
else s2 = (n / b1 + 1) * b2;

// 方案3
if (n % c1 == 0) s3 = n / c1 * c2;
else s3 = (n / c1 + 1) * c2;

// 判断大小,假设s1最小
int minn = s1;
if (s2 <= minn) minn = s2;
if (s3 <= minn) minn = s3;

// 输出
cout << minn;

36. P1046.NOIP2005.普及组.陶陶摘苹果

主讲老师 - 姚俞坚

1. 代码详解

// 十颗苹果的高度
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10;
cin >> a1 >> a2 >> a3 >> a4 >> a5 >> a6 >> a7 >> a8 >> a9 >> a10;

// 最大高度
int h;
cin >> h;

// 管它能不能够到,都站在板凳上
h += 30;

// 数量,初始化,否则有警告
int sum = 0;

// 判断
if (h >= a1) sum++;
if (h >= a2) sum++;
if (h >= a3) sum++;
if (h >= a4) sum++;
if (h >= a5) sum++;
if (h >= a6) sum++;
if (h >= a7) sum++;
if (h >= a8) sum++;
if (h >= a9) sum++;
if (h >= a10) sum++;

// 输出
cout << sum;

37. switch分支.垃圾分类

主讲老师 - 姚俞坚

1. swtich分支

  • 除了if … else条件分支,还有一种 switch … case 分支,用于变量均为等于成立的分支方案:

    // case 值1 表示 变量名 == 值1,成立的话,执行下面缩进的语句
    // break; 表示跳出switch,否则会继续判断后续的case;
    // default 相当于 else,在没有满足条件的时候执行,当然,可以省略这个;
    switch (变量名) {
    case 值1: 
        执行语句;
        break;
    case 值2:
        执行语句;
        break;
    case 值3:
        执行语句;
        break;
        ...
            
    default: 
        执行语句;
    }
    

2. 垃圾分类

  • 王二狗要下楼倒垃圾,垃圾分类有四种,他到底应该倒哪个桶呢?

    // 垃圾种类
    int n;
    // 输入提示
    cout << "请输入垃圾种类的序号:" << endl;
    cout << "1.表示可回收垃圾!" << endl;
    cout << "2.表示有害垃圾!" << endl;
    cout << "3.表示厨余垃圾!" << endl;
    cout << "4.表示其它垃圾!" << endl;
    cout << "请输入1-4:";
    cin >> n;
    
    // switch分支
    switch (n) {
    case 1:
        cout << "王二狗往可回收垃圾桶倒了垃圾!";
        break;
    case 2:
        cout << "王二狗往有害垃圾桶倒了垃圾!";
        break;
    case 3:
        cout << "王二狗往厨余垃圾桶倒了垃圾!";
        break;
    case 4:
        cout << "王二狗往其它垃圾桶倒了垃圾!";
        break;
    default:
        cout << "你往哪里倒???倒错了吧!";
        break;
    }
    

38. 1049.汉译英

主讲老师 - 姚俞坚

1. 代码详解

// 1-9
int n;
cin >> n;

// switch
switch (n) {
case 1:
	cout << "one";
	break;
case 2:
	cout << "two";
	break;
case 3:
	cout << "three";
    break;	
case 4:
	cout << "four";
	break;	
case 5:
	cout << "five";
	break;	
case 6:
	cout << "six";
	break;	
case 7:
	cout << "seven";
	break;	
case 8:
	cout << "eight";
	break;	
case 9:
	cout << "nine";
	break;	
default:
	cout << "out";
	break;
}

39. P5716.月份天数

主讲老师 - 姚俞坚

1. 代码详解

// 年,月
int y, m;
cin >> y >> m;

// switch判断月份
switch (m) {
// 合并相同的case
case 1: case 3: case 5: case 7: case 8: case 10: case 12:
    cout << 31;
    break;
case 4: case 6: case 9: case 11:
    cout << 30;
    break;
case 2:
    // 判断闰年平年
    if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) 
        cout << 29;
    else
        cout << 28;
    break;
}

40. for循环.累加和

主讲老师 - 姚俞坚

1. for语句

计算机最大的一个特性就是快速的重复执行有规律的运算,for循环语句 就是做这种事的

for (循环变量初始化;循环条件;循环变量增或减) {
    循环体
}
到达循环终值
未到达循环终值
开始程序
循环变量初始化
循环判断
结束循环
执行循环体
循环变量自增
  • 使用 for 循环语句,输出1-10这十个数字:

    // 输出1-10,每个数字换行
    // int i = 1; 循环变量初始化,从1开始
    // i <= 10; 循环判断,当i目前小于等于10时,继续执行循环体
    // i++;让循环变量进行累加,效果为:i = i + 1,没有这个过程就死循环啦
    // cout << i << endl; 循环体,也就是可执行语句的部分
    
    // 流程图文字版如下:
    // 第一步:int i = 1;初始化循环变量,这条语句只执行一次
    // 第二步:i <= 10; 判断循环条件;
    // 第三步:cout << i << endl; 第二步条件成立后,执行这一步,不成立,退出for语句;
    // 第四步:i++;增值变量;然后回到第二步继续
    // 后续一直循环2,3,4步,直到退出for语句位置;
    for(int i=1;i<=10;i++){
        cout << i << endl;
    }
    cout << "退出 for 循环后执行我!";
    

2. 累加和

  • 通过 for 循环 代码将一个月的零花钱保存起来,1号存1块,2号存2块…30号存30块,共存了多少钱。

    // 存钱变量
    int sum = 0;
    
    // 累加和
    for(int i=1;i<=30;i++){
        // sum = sum + i;
        sum += i;
    }
    
    // 输出
    cout << sum;
    

41. 1700.输出两位数中含2的整数

主讲老师 - 姚俞坚

1. 代码详解

// 十位 个位
int a, b;

// 循环10-99之间,包含10和99
for(int i=10;i<=99;i++){
    // 拆位
    a = i / 10;
    b = i % 10;

    // 判断
    if (a == 2 || b == 2) cout << i << endl;
}

42. 1058.求三位数的水仙花数

主讲老师 - 姚俞坚

1. 代码详解

// 百 十 个
int a, b, c;

// 循环三位数 100-999
for(int i=100;i<=999;i++){
    // 拆位
    a = i / 100;
    b = i / 10 % 10;
    c = i % 10;

    // 立方和
    if (a * a * a + b * b * b + c * c * c == i) cout << i << endl;
}

43. P5719.分类平均

主讲老师 - 姚俞坚

1. 代码详解

// 两个正整数
int n,k;
// 两类数之和,统计次数
int a = 0,b = 0,acount = 0;
// 输入
cin >> n >> k;

// 循环1-n之间
for(int i=1;i<=n;i++){
    // 求a数,并累加
    if (i % k == 0) {
        a += i;
        acount ++;
    } else {
        b += i;
    }
}

// 输出
printf("%.1f ", float(a) / acount);
printf("%.1f", float(b) / (n - acount));
// 这题是洛谷官方教材的题目,上面是我做的,循环次数略多
// 以下是官方给的方案,利用了倍数和等差公式
// 倍数通过 i = k 起步,i += k,每次增值k
// 等差数列求和:	
// 1-100的和,d为1时,等差公式:(a1 + an) x n / 2
// cout << (1 + 100) * n / 2;  // 5050

// 直接循环k的倍数即可
// 直接从k的值初始化,i+=k意思是i = i + k,每次增值k的倍数
for(int i=k;i<=n;i+=k) a += i;

// b的值,利用等差公式
b = (1 + n) * n / 2 - a;

// a的循环次数,n / k 即可
printf("%.1f ", float(a) / (n / k));
printf("%.1f", float(b) / (n - n / k));

44. 1395.小丽找数?

主讲老师 - 姚俞坚

1. 代码详解

// 整数
int n, a, b, c, d, count = 0;
cin >> n;

// 循环1-n
for(int i=1;i<=n;i++){
    // 拆位
    a = i / 1000;
    b = i / 100 % 10;
    c = i / 10 % 10;
    d = i % 10;

    // 判断需求
    if ((a + b + c + d) % 2 != 0 && (a + b + c + d) % 5 != 0) count++;
}

// 输出
cout << count;

45. for嵌套.九九乘法表

主讲老师 - 姚俞坚

1. for嵌套

for嵌套是什么意思?for语句的循环体再执行一个for语句吗?没错!

// 先来个简单的需求,完成下列图形
* * * * *
* * * * *
* * * * *
* * * * *
* * * * *
// 首先,开启纬度思想,一维即:一行一条线;二维则:多行多列是个面
// 第一步,先考虑输出一行
for(int i=1;i<=5;i++){
	cout << "* ";
}

// 第二步,将一行改成一列试试,为后续扩展铺路
for(int i=1;i<=5;i++){
    cout << "* " << endl;
}

// 第三步,将每一列当成一个for循环,再铺出一行
for(int i=1;i<=5;i++){
    for(int j=1;j<=5;j++){
        cout << "* ";
    }
    cout << endl;		// 一列换一次行
}

2. 九九乘法表

利用 for循环 嵌套,实现一个不重复的 九九乘法表

// 第一步:先考虑1x1=1...1x9=9 这一列
for(int i=1;i<=9;i++){
    printf("1x%d=%d\n", i, 1 * i);
}

// 第二步:将输出的每一项换成for循环输出9项
// 循环逻辑:
// i = 1时,j = 1 2 3 4 5 6 7 8 9
// i = 2时,j = 1 2 3 4 5 6 7 8 9
// ...
// i = 9时,j = 1 2 3 4 5 6 7 8 9
for(int i=1;i<=9;i++){
    for(int j=1;j<=9;j++){
        printf("%dx%d=%2d ", i, j, i * j);
    }
    printf("\n");
}

// 第三步:去掉右上部分的重复, 1 x 2 = 2 和 2 x 1 = 2 这种
// 问题:每次j都循环满9次是导致重复的根源,如何处理?
// 解题:第1行,后8个是重复的,第2行,后7个是重复的,以此类推;
// 编码:那么只要将每次循环的次数和i保持一致即可。
for(int i=1;i<=9;i++){
    for(int j=1;j<=i;j++){
        printf("%dx%d=%2d ", i, j, i * j);
    }
    printf("\n");
}

46. 1492.空心正方形

主讲老师 - 姚俞坚

1. 代码详解

// 正方形边数
int n;
cin >> n;

// 循环1-n
for(int i=1;i<=n;i++){
    for(int j=1;j<=n;j++){
        // 第一行和第n行是满星
        // 第一列和第n列也要星
        if (i == 1 or i == n or j == 1 or j == n)
            cout << "*";
        else
            cout << " ";
    }
    cout << endl;
}

47. 1006.打印星号三角形

主讲老师 - 姚俞坚

1. 代码详解

// 行数
int n;
cin >> n;

// 最外层控制行数,比如样例的5行
for(int i=1;i<=n;i++) {
    // 中层控制三块三角形
    for(int j=1;j<=3;j++){
        // 假设第一次循环
        // 第一行星号前后有4个空格,那就需要循环4次,星号1次
        // 以此类推:第二行,前后3个空格,星号3次
        for(int z=1;z<=n-i;z++){
            cout << " ";
        }
        // 星号是:1 3 5 每行+2:i*2-1
        // i = 1 z<=1*2-1=1
        // i = 2 z<=2*2-1=3
        // i = 3 z<=3*2-1=5
        for(int z=1;z<=i*2-1;z++){
            cout << "*";
        }
        for(int z=1;z<=n-i;z++){
            cout << " ";
        }
    }
    cout << endl;
}

48. 1019.求1!+2!+…+N!

主讲老师 - 姚俞坚

1. 代码详解

// 整数n, 总和sum
int n, sum = 0;
cin >> n;

// 循环1-n
for(int i=1;i<=n;i++){
    // 希望累加的过程
    // i = 1, 1
    // i = 2, 1 x 2
    // i = 3, 1 x 2 x 3
    // i = 4, 1 x 2 x 3 x 4
    // 最后,把每一行乘积的结果累加
    int temp = 1;
    for(int j=1;j<=i;j++){
        // 1 * 1 * 2 * 3 * 4
        temp *= j;
    }
    sum += temp;
}

cout << sum;

49. 1519.求1~n中每个数的因子

主讲老师 - 姚俞坚

1. 代码详解

// 整数n
int n;
cin >> n;

// 循环1-n
for(int i=1;i<=n;i++){
    // 输出
    cout << i << ":";
    // 循环1-i
    for(int j=1;j<=i;j++){
        // 求因子
        if (i % j == 0) cout << j << " ";
    }
    // 换行
    cout << endl;
}

50. P5724.求极差 / 最大跨度值

主讲老师 - 姚俞坚

1. 代码详解

// n,表示要输入比较的数
// 求最大最小值
int n, maxn = -1, minn = 1001;
cin >>n;

// 循环赋值 
for(int i=1;i<=n;i++){
    // 临时变量
    int temp;
    cin >> temp;

    // 求最大最小
    if (temp < minn) minn = temp;
    if (temp > maxn) maxn = temp;
}

// 极差
cout << maxn - minn;

51. P1420.最长连号

主讲老师 - 姚俞坚

1. 代码详解

// n,a,count,maxn
int n, a, prev, count = 1, maxn = 0;
cin >> n;
// 由于需要邻值对比,先单独把第一个值保存至prev
cin >> prev;

// 1-n循环,由于首值已录,这里直接从第2值开始
for(int i=2;i<=n;i++){
    cin >> a;
    // 判断当前值是否是上一值+1,计数器+1
    if (a == prev + 1) count++;
    // 计时器还原
    else count = 1;

    // 求最大值
    if (maxn < count) maxn = count;
    // 将当前值换成下一个
    prev = a;
}

// 输出
cout << maxn;

52. 变量作用域.退出循环

主讲老师 - 姚俞坚

1. 变量作用域

变量作用域分为局部和全局,在之前的解题中存在不同位置,效果也不尽相同;

// 首先,函数还没学过,不考虑

int a = 5;
// 在if里面声明的变量和外部的区别
if (5 > 3) {
    // 判断体内可以访问外部变量a
    // 此时a可以理解为全局变量(不考虑函数),在哪里可以访问(赋值取值)
    cout << a;
}

// 在if体内的变量
if (5 > 3) {
    int b = 3;
    cout << b;
}

// 访问不了b,因为它是局部变量,只能在所在的if体内访问
cout << b;
// 这里int i属于for体内的局部变量i
for(int i=1;i<=5;i++){
    //...
}

// 外部无法访问,直接报错
cout << i;

// 可以提到外面来声明来保证全局性
int i;
for(i=1;i<=5;i++){
    //...
}

// 可以访问,并且是6,因为for最后执行是i++
cout << i;

// 之前短除法的临时变量
for(int i=1;i<=10;i++){
    // 这里的tmp在for外部就无法访问了
    // 它就是临时工,在for体内用的
    // 所以总结:想要在体内用不想在外面用,就在体内声明
    // 如果要全局都能使用,就在外部声明,比如程序代码的第一行
    int tmp = 0
}

2. break退出

break 的作用是在循环体内,可设置条件来退出这个循环;

// break退出
for(int i=1;i<=10;i++){
    // 当遇到5退出整个循环
    if (i == 5) break;
    // 输出i
    cout << i << endl;
}

3. continue退出

continue 的作用是在循环体内,可设置条件来退出当前这次循环,然后继续执行下一次循环;

// continue退出
for(int i=1;i<=10;i++){
    // 当遇到5退出当前循环,continue需要卸载循环体最前面才有意义
    if (i == 5) continue;
    // 输出i
    cout << i << endl;
}

53. P1075.NOIP2012.普及组.质因数分解

主讲老师 - 姚俞坚

1. 代码详解

// 质数 = 素数,只能被1和本身整除
// n
int n;
cin >> n;

// 循环2~n-1
for(int i=2;i<=n-1;i++){
    // 判断i是否为因子,找到第一个即最小的因子
    // 天坑:此题如果测试数据n是20,那因子为2,10,则10最大,但10不是质数
    // 审题:题目说了由两个不同质数的乘积,10不是质数,所以测试数据不会给20让你测
    // 再审题:由两个不同的质数,不是多个,还必须是质数。。。20 不符合要求的
    if (n % i == 0) {
        // 求出较大的数
        cout << n / i;
        break;
    }
}

54. P5723.质数口袋

主讲老师 - 姚俞坚

1. 代码详解

// n, count, sum
int n, count = 0, sum = 0;
cin >> n;

// 循环2~n-1
for(int i=2;i<=n;i++){
    // 判断质数
    bool flag = true;
    for(int j=2;j<=i-1;j++){
        // 能被整除,说明不是质数,退出j循环
        if (i % j == 0) {
            flag = false; 
            break;
        }
    }
    // 既然不是质数,退出i的本次循环,直接循环下一个i
    // continue 在这里卡住,不再执行后续代码
    if (!flag) continue;
    // 判断到目前质数的和是否大于n,大于直接break退出整个i循环
    if (sum + i > n) break;
    // 如果没被continue卡住,则说明是质数,输出i,并count+1,累加sum
    cout << i << endl;
    count++;
    sum += i;
}

// 输出计数器
cout << count << endl;

55. P5725.求三角形

主讲老师 - 姚俞坚

1. 代码详解

// n
int n;
cin >> n;

// 循环1-n*n
for(int i=1;i<=n*n;i++) {
    // 个位数,补零
    if (i < 10) cout << 0 << i;
    else cout << i;

    // 判断n的倍数,换行
    if (i % n == 0) cout << endl;
}

// 空一行
cout << endl;

// 循环1-n,负责n列,计数器count
int count = 1;
for(int i=1;i<=n;i++){
    // 输出空格
    for(int j=1;j<=n-i;j++){
        cout << "  ";
    }
    // 输出数字
    for(int j=1;j<=i;j++){
        if (count < 10) cout << 0 << count;
        else cout << count;
        count++;
    }
    cout << endl;
}

56. P5726.打分

主讲老师 - 姚俞坚

1. 代码详解

//n, sum, maxn, minn
int n, sum = 0, maxn = -1, minn = 11;
cin >> n;

// 循环1-n
for(int i=1;i<=n;i++){
    // 输入分数
    int c;
    cin >> c;

    // 累加分
    sum += c;

    // 求最大最小值
    if (maxn < c) maxn = c;
    if (minn > c) minn = c;
}

// 去掉最大值和最小值
sum = sum - maxn - minn;

// 计算输出分数
printf("%.2f", (float)sum / (n - 2));

57. P2669.NOIP2015.普及组.金币

主讲老师 - 姚俞坚

1. 代码详解

// k天数, coin金币, day当前累计天
int k, coin = 0, day = 0;
cin >> k;

// 简单捋一下
// i=1, 第1天:+1
// i=2, 第2,3天:+2 +2
// i=3, 第4,5,6天:+3 +3 +3
// ...

// 现在给出的k是天数

// 根本不清楚i的末值是多少,那就无限循环吧(死循环)
// 死循环可以将条件去掉,但保留分号,循环体通过判断退出即可
// 外层循环,表示轮次,第1次1天,第2次2,3天,第3次4,5,6天中的次
for(int i=1;;i++) {
    // 将轮次中的天数累加到day里
    for(int j=1;j<=i;j++){
        // 累加天数
        day++;
        // 累加金币
        coin += i;

        // 退出机制
        if (day == k){
            cout << coin << endl;
            return 0;
        }
    }
}

58. while和do while循环

主讲老师 - 姚俞坚

1. while

while 循环相当于 for 循环,可以不用计数器,需要先进行条件判断,也可设置死循环

// 死循环:条件是1或者true,让它永远成立即可
while(1){
    cout << 123;
}

// 利用计数器输出1-10
int a = 1;
while(a <= 10) {
    cout << a << endl;
    a++;
}

// 死循环中途退出
// 支持break、continue
int a = 1;
while(1){
    if (a == 5) break;
    cout << 123;
    a++;
}

2. do while

do while 循环相当于 while 循环,可以将条件判断至于循环体下方,让其无条件先循环一次

// 不管条件是否满足,至少要执行一次循环体
int a = 1;
do{
    cout << 123;
} while(a < 0);

59. 1062.求落地次数

主讲老师 - 姚俞坚

1. 代码详解

// m高度,审题有0.5,所以是浮点型
float m = 100;
// count计数器
int count = 0;

// 大于等于0.5就一直循环
while(m >= 0.5){
    count++;
    m /= 2.0;
}

cout << count;

60. 1261.韩信点兵

主讲老师 - 姚俞坚

1. 代码详解

// 人数
int n = 0;

// 不知道人数,只能无脑死循环
while(1){
    // 每循环一次n+1,统计人数
    n++;

    // 余数同时成立即可
    if (n % 5 == 1 && n % 6 == 5 && n % 7 == 4 && n % 11 == 10) {
        cout << n;
        break;
    }
}

61. P1423.小玉在游泳

主讲老师 - 姚俞坚

1. 代码详解

// s目标距离, f每次游泳的时间, count步数
float s, f = 2, count = 0;
cin >> s;

// 先别废话,让她游
do {
    // 每次游泳就要减去一次距离
    s -= f;
    // 每次游泳的距离是上一次的0.98
    f *= 0.98;
    // 累加步数
    count++;

} while(s > 0);

// 输出步数
cout << count;

62. 短除法.新式拆位

主讲老师 - 姚俞坚

1. 短除拆位

之前我们拆位使用了整除+求余的方式,但对于不确定位数的整数就会捉襟见肘

// 要求输入三至五位整数
// 将每一位输出
int n;
cin >> n;

// 使用短除法
// 通过求余得到末尾:
// 比如 123 % 10 = 3 
// 然后 12 % 10 = 2 ... 1 % 10 = 1...最终除数为0
while(n != 0) {
    // 输出拆位
    cout << n % 10 << endl;
    // 整除
    n /= 10;
}

63. 1750.有0的数

主讲老师 - 姚俞坚

1. 代码详解

int n, count = 0;
cin >> n;

// 循环1-n,1-9不含0,直接从10开始
for(int i=10;i<=n;i++){
    // 短除
    int temp = i;

    while(temp != 0) {
        // 102: 2..0(+1)..1
        if (temp % 10 == 0) {
            count++;
            break;		// 只要包含0就行了,退while
        }

        // 整除
        temp /= 10;
    }
}

cout << count;

64. P1307.NOIP2011.普及组.数字反转

主讲老师 - 姚俞坚

1. 代码详解

// n原数,f新数
int n, f = 0;
cin >> n;

// 不用考虑负数
while(n != 0){
    // 拆位
    int g;
    g = n % 10; 

    // 假设123,上一轮f得到了3,这次要30+2=32,最后要320+1=321
    // 第一轮,由于f是0,所以,f * 10 + g = 3
    f = f * 10 + g;

    // 整除
    n /= 10;
}

cout << f;

65. P1980.NOIP2013.普及组.计数问题

主讲老师 - 姚俞坚

1. 代码详解

int n, x, count = 0;
cin >> n >> x;

// 循环1-n
for(int i=1;i<=n;i++){
    //拆位
    int temp = i;

    while(temp != 0) {
        if (temp % 10 == x) count++;
        temp /= 10;
    }
}

cout << count;

66. 1846.阿尔法乘积

主讲老师 - 姚俞坚

1. 代码详解

// x是个位,α乘积即x本身
int x;
cin >> x;

// 大于10,忽略个位数
while(x >= 10){
    // 初始乘积变量
    int temp = 1;

    // 拆位循环
    while(x != 0) {
        // 获取个位
        int g = x % 10;

        // 乘积,非零
        if (g != 0) temp *= g;

        // 整除
        x /= 10;
    }

    // 将乘积返回给x,进入下一次循环
    x = temp;
}

cout << x;

67. P1089.NOIP2004.提高组.津津的储蓄计划

主讲老师 - 姚俞坚

1. 代码详解

// money钱, cost花销, mather妈
int money = 0, cost = 0, mather = 0;

// 1-12月循环
for(int i=1;i<=12;i++) {
    // 每个月+300元
    money += 300;
    // 输入这个月花销
    cin >> cost;

    // 如果持有100或以上,就把整百交给妈妈
    // 比如有180,交给妈妈100,有280,交给妈妈200
    // 扣去当月花销
    money -= cost;
    while (money >= 100) {
        mather += 100;
        money -= 100;
    }

    // 如果发现钱是负的
    if (money < 0) {
        printf("-%d", i);
        return 0;
    }
}

// 输出money
cout << money + mather + (mather * 0.2);

68. 简单穷举.1351.买公园门票

主讲老师 - 姚俞坚

1. 穷举说明

穷举即枚举,我们会在下一套课程中讲解 暴力枚举,那么现在先简单的了解下

  • 其实,在之前循环课程中,我们经常使用穷举法,只是没有挑明:
    • 通过不断循环,让大量的值进行比对验证,得出想要的结果;

2. 买公园门票

// 假设只有一个小孩,成人拥有的票钱 = 40 - 3
// 成人票最多买:37 / 8 = 4张,循环1-4张
for(int i=1;i<=(40-3)/8;i++) {
    // 第一次循环:1张成人票,减去-8,再看看买小孩的票,能否整除
    // 第i次以此类推
    int x;
    // 得到买小孩票的钱
    x = 40 - i * 8;
    // 判断是否能整除
    if (x % 3 == 0) cout << i << " " << x / 3 << endl;
}

69. 1025.兑换硬币

主讲老师 - 姚俞坚

1. 代码详解

// 100分, 累计count
int f = 100, count = 0;

// 先从5分开始,1分2分至少一个:(100 - 2 - 1) / 5 = 5分钱个数
for(int i=1;i<=(100-2-1)/5;i++){
    // 嵌套2分:(100 - 5 - 1) / 2 = 2分个数
    for(int j=1;j<=(100-5-1)/2;j++){
        // i第一轮,j第一轮:一个5分+一个2分,93个1分
        // i第一轮,j第二轮:一个5分+两个2分,91个1分
        // i第一轮,j第三轮:一个5分+三个2分,89个1分
        // ...
        // i第三轮,j第一轮:三个5分+一个2分,83个1分
        // ...
        // i第三轮,j第五轮:三个5分+五个2分,75个1分
        // ...


        // 得到1分钱银币的总分数
        // 在循环中,值>=1,说明可以整除1
        if (f - (i * 5 + j * 2) >= 1) count++; 
    }
}

cout << count;

70. 1342.怎样种树?

主讲老师 - 姚俞坚

1. 代码详解

// 总树木
int n;
cin >> n;

// 从桃树开始,梨树和苹果树至少各两棵(偶数限制)
// 累加也是偶数:i=i+2
for(int i=2;i<=n-2-2;i=i+2){
    // 然后是梨树
    for(int j=2;j<=n-2-2;j=j+2){
        // i第一轮,j第一轮:桃树2,梨树2,苹果树18-2-2=14
        // 和兑换银币那个例子一样,下面不循了

        // 得到当前轮苹果树
        int p = n - i - j;
        // 规则判断成立时输出三种树
        if (i <= j && j <= p)
            printf("%d %d %d\n", i, j, p);
    }
}

71. 批量存储.一维数组

主讲老师 - 姚俞坚

1. 数组声明

数组分为:一维、二维、多维,大部分情况下只用一维,少量二维,多维很少

  • 变量只能存储一条数据,数组可以存储多条数据;

  • 比如我要声明一个可以存放10条数据数组:

    • 格式为:类型名 数组名[表达式] 注:[] 可以是数字,也可以是a-1的运算;
    // 声明可以存放10条数据的数组,数组里的值(或叫元素)为整数
    int a[10];
    
    a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]
    78596612912898735276
  • 从上述的数组数据结构图中,总结几点:

    • int a[10]:表示声明一个可以存放10条整数的数组a;
    • 其中[0~9],我们称为下标,它的范围是0-9之间;
    • 对某一个下标进行赋值取值,可以是:a[5] = 128;
    // 对数组a下标5,也就是第6个位置赋值
    a[5] = 128;
    // 输出123
    cout << a[5];
    
    // 没有赋值的数组会随机出现不同值
    cout << a[3];
    
    // 当然这里有一个目前还没有学习的概念:全局变量和局部变量
    // 如果把int a[10]放在int main()外部,就是全局,那么不赋值默认就是0
    // 如果是局部变量:没有赋值的还有可能默认0,我们可以用循环查看
    for(int i=0;i<=19;i++){
        printf("a[%d]=%d\n", i, a[i]);
    }
    
  • 第二种数组的赋值方式,采用花括号对声明的数组直接赋值:

    // 花括号直接赋值
    int a[10] = {78, 59, 66, 12, 9, 128, 98, 73, 52, 76};
    // 通过循环逐步输出,注意,i从0开始,i<=9或<10
    for(int i=0;i<=9;i++){
        printf("a[%d]=%d\n", i, a[i]);
    }
    
    // 如果你设置了a[20],但{}里只有10个数据,则会用整数0填充
    for(int i=0;i<=19;i++){
        printf("a[%d]=%d\n", i, a[i]);
    }
    
  • 如果不确定赋值的个数,可以采用动态方案赋值:

    // 但这样,就无法得知长度了;需要通过以后学习的sizeof()函数来获取,先不深入探讨
    int a[] = {1, 2, 3, 4, 5}
    
  • 至于无法一开始初始化指定值,又怕未赋值导致随机值,可以先初始化零;

    // 初始化0:方案一
    int a[10] = {};
    // 初始化0:方案二
    int a[10] = {0};
    

2. 下标越界

什么是下标越界:声明时,超过了指定的范围就是下标越界,规定:不要越界;

  • 下标越界,有些平台会报异常,有些不报错(这种最要命,程序没错,数据错了检查不出来)

  • 所以,不要越界;

  • 比如,你int a[10],你赋值时就初始化时,就无法对a[20]赋值,导致随机数字;

    int a[10] = {0};
    cout << a[12];
    

72. 1153.查找“支撑数”

主讲老师 - 姚俞坚

1. 代码详解

// 整型数组,长度100,默认0,废弃a[0],+1
int a[101] = {0};
int n;
cin >> n;

// 循环1-n,注意:如果从1开始,废弃a[0]
// 循环0-n,注意:i<n 去掉等号
for(int i=1;i<=n;i++) cin >> a[i];

// 支撑数:不在第一位,不在最后一位,掐头去尾
for(int i=2;i<=n-1;i++){
    // 当前值比左右两边都大
    // 上一个值:a[i-1],下一个值:a[i+1]
    if (a[i] > a[i-1] && a[i] > a[i+1]) cout << a[i] << endl; 
}

73. 1354.拿到某个数的概率

主讲老师 - 姚俞坚

1. 代码详解

// 球
int a[101] = {0}, n, cnt = 0;
cin >> n;

// 赋值
for(int i=1;i<=n;i++) cin >> a[i];

// 对比值
int x;
cin >> x;

// 统计
for(int i=1;i<=n;i++){
    // 判断
    if (a[i] == x) cnt++;
}

// 求概率
printf("%.2f", cnt / float(n));

74. 1426.年龄与疾病

主讲老师 - 姚俞坚

1. 代码详解

// 病人
int a[101] = {0}, n;
cin >> n;

// 赋值
for(int i=1;i<=n;i++) cin >> a[i];

// 四个年龄段
int cnt[4] = {0};

// 循环病人
for(int i=1;i<=n;i++){
    // 判断
    if (a[i] >= 0 && a[i] <= 18) cnt[0]++;
    if (a[i] >= 19 && a[i] <= 35) cnt[1]++;
    if (a[i] >= 36 && a[i] <= 60) cnt[2]++;
    if (a[i] >= 61) cnt[3]++;
}

// 循环年龄段,注意,年龄是从下标0开始赋值的 i<=3 或 i<4 
for(int i=0;i<=3;i++){
    printf("%d %.2f%%\n", cnt[i], cnt[i] / float(n) * 100);
}

75. P1428.小鱼比可爱

主讲老师 - 姚俞坚

1. 代码详解

// 鱼
int a[101] = {0}, n;
cin >> n;

// 赋值
for(int i=1;i<=n;i++) cin >> a[i];

// 外层循环所有鱼
for(int i=1;i<=n;i++){
    // 思路:让当前的鱼和除了自己的每一条对比,比自己不可爱的就+1
    int cnt = 0;
    // 内层循环要对比的鱼
    // 因为鱼只能看到它左边的鱼,所以要忽略它右边的鱼
    for(int j=1;j<=n;j++){
        // 碰到自己了,退出
        if (i == j) break;
        // 累计,审题后得知等于不计数,必须大于
        if (a[i] > a[j]) cnt++;
    }
    // 输出
    cout << cnt << " ";
}

76. 2029.缺失的数字

主讲老师 - 姚俞坚

1. 代码详解

// 数
int a[100001] = {0}, n, x;
cin >> n;

// 循环1-n
for(int i=1;i<=n-2;i++){
    // x
    cin >> x;
    // 将a数组中下标为x,即a[x]做个标记,比如设置为1
    a[x] = 1;
}

// 再次循环1-n
for(int i=1;i<=n;i++){
    // 输出值为零的数组元素
    if (a[i] == 0) cout << i << " ";
}

77. 1428.找同学的位置

主讲老师 - 姚俞坚

1. 代码详解

int n, a[101] = {0};
cin >> n;

// 循环1-n学号,赋值
for(int i=1;i<=n;i++) cin >> a[i];

// 求最大最小值位置
int minn = 101, maxn = -1, min_index = 0, max_index = 0;

for(int i=1;i<=n;i++){
    if (a[i] < minn) minn = a[i], min_index = i;
    if (a[i] > maxn) maxn = a[i], max_index = i;
}

cout << max_index << " " << min_index;

78. P1427.小鱼的数字游戏

主讲老师 - 姚俞坚

1. 代码详解

// 本题并没有让你输入n限制数组赋值个数,可以考虑while
int a[101] = {0};

// 新知识点:++i 和 i++ 的区别
// int i = 1;
// int b = ++i;	// 或 i++
// cout << b;
// ++i 语法 是将本身i累计后再参与运算;
// i++ 语法 是先将i参与运算(比如赋值),然后本身再累加

// 融合到数组中
// int i = 1;
// a[i++] = 100;	// 如果i当前为1,那么a[1] = 100,然后i再变成2
// cout << a[1];	// 100
// cout << a[2];	// 0

int i = 0, tmp;

// 死循环走起
while(true) {
    cin >> tmp;
    if (tmp == 0) break;
    // 赋值
    a[++i] = tmp;
}

// 看下i的值和数量是否对的上
//cout << i;

// 倒数,从末尾循环到开头
while(i != 0){
    cout << a[i--] << " ";
}

79. P5727.冰雹猜想

主讲老师 - 姚俞坚

1. 代码详解

int n, a[101] = {0}, i = 1;
cin >> n;

// 第一个
a[1] = n;
// 循环
while(n != 1) {
    // 判断偶数
    if (n % 2 == 0)
        n = n / 2;
    else 
        n = n * 3 + 1;

    a[++i] = n;
}

// 倒着输出
while(i != 0){
    cout << a[i--] << " ";
}

80. P1047.NOIP2005.普及组.校门外的树

主讲老师 - 姚俞坚

1. 代码详解

int l, m, a[10001] = {0};
cin >> l >> m;

int u, v = 0;
// m行
for(int i=1;i<=m;i++){
    cin >> u >> v;
    // 从u点到v点
    for(int j=u;j<=v;j++){
        a[j] = 1;	
    }
}

int total = 0;
// l总树木,题目说从0开始
for(int i=0;i<=l;i++){
    if (a[i] == 0) total++;
}

// 输出
cout << total;

81. P1554.梦中的统计

主讲老师 - 姚俞坚

1. 代码详解

int m, n, a[10] = {0};
cin >> m >> n;

// 循环n-m
for(int i=m;i<=n;i++){
    // 短除拆位
    int tmp = i;

    while(tmp != 0) {
        a[tmp % 10]++;			
        tmp /= 10;
    }
}

// 统计
for(int i=0;i<=9;i++){
    cout << a[i] << " ";
}

82. P2141.NOIP2014 普及组.珠心算测验

主讲老师 - 姚俞坚

1. 代码详解

int n, a[101] = {0}, b[101] = {0}, cnt = 0;
cin >> n;

// 循环n
for(int i=1;i<=n;i++) cin >> a[i];

// i 从数组第一位开始
for(int i=1;i<=n;i++) {
    // j 从数组第二位开始,这样实现:第一位+第二位
    for(int j=i+1;j<=n;j++) {
        // z 用来对比值
        for(int z=1;z<=n;z++) {
            if (a[i] + a[j] == a[z] && b[z] != 1) {
                // 5
                // 2 5 3 4 7
                // 这一组数据中:2 + 5 = 7 和 3 + 4 = 7 算重复,要去重
                // 但题目中很难知道要剔除这种重复,是一个坑点,从错误的测试点获知的
                // 再审题,她说有多少个数?不是几种方案,所以,两个结果7算一个数

                // 4
                // 1 4 5 2
                // 这一组重复为:1 + 4 = 5, 4 + 1 = 5;要去掉一个重复,保留一个
                // 可以暴力枚举,但只要每次j向后移一位,即可自然去重
                // printf("%d+%d=%d\n", a[i], a[j], a[z]);

                // i : 1 4 5 2
                // j : 1 4 5 2 (j+1)
                // z : 1 4 5 2
                // 第一轮:1 + 4, 1 + 5, 1 + 2
                // 第二轮:4 + 5, 4 + 2
                // 第三轮:5 + 2

                cnt++;
                // 标记a[z]的结果数字被统计过了
                b[z] = 1;
            }
        }
    }
}

// 统计
cout << cnt;

83. 1118.既生瑜,何生亮!

主讲老师 - 姚俞坚

1. 代码详解

int x, y;
cin >> x >> y;

// 循环
for(int i=x;i<=y;i++){
    // 短除拆位
    int tmp = i * i;

    // 不是7位数,直接下一次循环
    if (tmp < 1000000 || tmp > 9999999) continue;

    // 临时数组
    int a[10] = {0};

    while(tmp != 0){
        // 个位求余
        a[tmp % 10]++;
        // 去掉个位
        tmp /= 10;
    }

    // 判断重复
    bool flag = true;
    for(int j=0;j<=9;j++){
        if (a[j] > 1) {
            flag = false;
            break;
        } 
    }

    // 输出
    if (flag) cout << i << endl;

}

84. 1165.下载电影

主讲老师 - 姚俞坚

1. 代码详解

int n, m;
float maxn = -1.0;
cin >> n >> m;

// 数组赋值
int a[101] = {0};
for(int i=1;i<=n;i++) cin >> a[i];


// 循环1-n
for(int i=1;i<=n;i++){
    // 每次循环从i的值开始
    // 假设 n m : 6 3  数组:3 6 1 5 6 4
    // 第一轮:3 6 1
    // 第二轮:6 1 5
    // 第三轮:1 5 6

    // 循环,不足m个,则不再统计
    if (i + m - 1 <= n) {
        float sum = 0.0;
        for(int j=i;j<=i+m-1;j++){
            sum += a[j];
        }
        // 对比
        if (sum / m > maxn) maxn = sum / m;
    }
}

// 输出
printf("%.2f", maxn);

85. 1400.补发礼物?

主讲老师 - 姚俞坚

1. 代码详解

int n, a[101] = {0};
cin >> n;

// 赋值
for(int i=1;i<=n;i++) cin >> a[i];

// 处理
for(int i=1;i<=n;i++){
    // 条件1:本身礼物数>=10
    // 条件2:礼物数是4的倍数

    // 满足条件,直接退
    if (a[i] >= 10 && a[i] % 4 ==0) 
        continue;
    else {
        // 补礼物循环次数,比如初始0,至多补12次
        for(int j=1;j<=12;j++){
            a[i] += 1;
            if (a[i] >= 10 && a[i] % 4 ==0) break;
        }
    }
}

// 由于课程进度未学习到函数sort排序或排序算法(冒泡、选择、插入等)
// 属于超纲提高难度(类似打游戏中越级打怪,或禁翻滚、禁药打怪)

// 只用之前学习过的几个知识点将排序做起来
// 知识点1:求极值(最大最小值)
// 知识点2:嵌套循环,外层次数,内层对比
// 知识点3:标记已知最大值,去重复,避免再次对比
// i:5 次循环
// j:12 32 12 24 20 对比数据

// 声明新数组,存放排序好的
int z[101] = {0};
for(int i=1;i<=n;i++){
    // 初始化最大值
    int maxn = -1;
    // 初始化找到的最大值的位置
    int index = -1;
    for(int j=1;j<=n;j++){
        // 求出当前最大值
        if (a[j] > maxn) maxn = a[j], index = j;
    }
    // 将原本最大值的位置标记,设置-1
    a[index] = -1;
    // 将最大值赋值给当前i循环的位置,也就是最前面
    z[i] = maxn;
}

// 输出所有
for(int i=1;i<=n;i++) cout << z[i] << " ";

86. 1965.奖学金

主讲老师 - 姚俞坚

1. 代码详解

int n, a[101] = {0};
cin >> n;

// 赋值
for(int i=1;i<=n;i++) cin >> a[i];

// 新数组
int z[101] = {0};
// 嵌套循环求极值
for(int i=1;i<=n;i++){
    // 初始化最大值和位置
    int maxn = -1, index = -1;
    // 求最大值
    for(int j=1;j<=n;j++){
        if (a[j] > maxn) maxn = a[j], index = j;
    }
    // 将原本的最大值标记-1
    a[index] = -1;
    // 将最大值赋值给新数组当前i的位置
    z[i] = maxn;
}

// 输出
for(int i=1;i<=n;i++){
    // 判断
    if (i <= 2) printf("%d %d\n", z[i], 500);
    if (i >= 3 && i <= 6) printf("%d %d\n", z[i], 300);
    if (i >= 7 && i <= 10) printf("%d %d\n", z[i], 100);
    if (i >= 11) printf("%d %d\n", z[i], 0);
}

87. P2550.AHOI2001.彩票摇奖

主讲老师 - 姚俞坚

1. 代码详解

int n, a[8] = {0}, b[8] = {0};
cin >> n;

// 彩票有7个号码,存储中奖号码
for(int i=1;i<=7;i++) cin >> a[i];

// 循环n组购买彩票的号码
for(int i=1;i<=n;i++){
    // 计数器
    int cnt = 0;
    // 读入一组7位号码
    for(int j=1;j<=7;j++){
        int tmp;
        cin >> tmp;

        // 读入的数和中奖的7位一一对比
        for(int z=1;z<=7;z++){
            if (tmp == a[z]) cnt++;
        }
    }
    // 假设cnt++两次,是五等奖
    // b[2] = 1,五等奖显示在第6个位置上
    // 假设还有一张也是五等奖b[2] = 2张
    b[cnt]++;
}

// 倒序
for(int i=7;i>=1;i--){
    cout << b[i] << " ";
}

88. 二维数组.多维数组

主讲老师 - 姚俞坚

1. 数组声明

所谓的二维数组,就是数组里还有一个数组,类似嵌套循环,多维数组就是数组里的数组里的数组;

  • 声明格式:

    数据类型 数组名[行数][列数]		// 就是两层嵌套循环
    
  • 二维数组构建一个矩阵表格:

    a[0,0] -> 78a[0,1] -> 102a[0,2] -> 44
    a[1,0] -> 92a[1,1] -> 165a[1,2] -> 92
    a[2,0] -> 67a[2,1] -> 278a[2,2] -> 39
    // 上面的构建,从0开始的,也可以和之前废弃0从1开始
    int a[3][3];
    
    // 硬赋值
    a[0][0] = 78;
    a[0][1] = 102;
    a[0][2] = 44;
    a[1][0] = 92;
    a[1][1] = 165;
    a[1][2] = 95;
    a[2][0] = 67;
    a[2][1] = 278;
    a[2][2] = 39;
    
    // 二维数组较好理解的初始化,内嵌的花括号表示一行,逗号结束表示换行
    int b[3][3] = {{78, 102, 44}, {92, 165, 95}, {67, 278, 39}}
    
    // 二维数组本质也是一维数组,可按照一维方式赋值
    int b[3][3] = {78, 102, 44, 92, 165, 95, 67, 278, 39};
    
    // 嵌套循环输出
    // 输出矩阵为:
    // 第一轮:a[0][0] a[0][1] a[0][2]
    // 第二轮:a[1][0] a[1][1] a[1][2]
    // 第三轮:a[2][0] a[2][1] a[2][2]
    for(int i=0;i<=2;i++){
        for(int j=0;j<=2;j++){
            printf("%5d", a[i][j]);
        }
      printf("\n");
    }
    

2. 多维数组

多为数组,三维:数组里的数组里的数组,不用理解到其它学科的纬度

// 题外话:不用理解成几何里三维立体,四维超立体,或天文里的四维时空,没那么复杂
// 用三维表示地球村,一维:地球,二维:国家:三维:省份,用数字代替
int b[3][3][3] = {
    {
        {1, 2, 3}, {4, 5, 6}, {7, 8, 9}
    },
    {
        {11, 11, 12}, {13, 14, 15}, {16, 17, 18}
    },
    {
        {20, 21, 22}, {23, 24, 25}, {26, 27, 28}
    }
};

for(int i=0;i<=2;i++){
    for(int j=0;j<=2;j++){
        cout << "( ";
        for(int z=0;z<=2;z++){
            cout << b[i][j][z] << " ";
        }
        cout << "), ";	
    }
    cout << endl;
}

89. 1272.郭远摘苹果

主讲老师 - 姚俞坚

1. 代码详解

int n, m, a[11][11] = {0};
cin >> n >> m;

// i从0开始也行,从1开始也行
for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++) cin >> a[i][j];
}

// 最大值没给范围,那就把第一个值初始
int maxn = a[1][1], minn = a[1][1];
for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
        // 求最大值
        if (maxn < a[i][j]) maxn = a[i][j];
        // 求最小值
        if (minn > a[i][j]) minn = a[i][j];
    }
}

// 求差
cout << maxn - minn;

90. 1384.靶心数

主讲老师 - 姚俞坚

1. 代码详解

int n, m, a[101][101] = {0};
cin >> n >> m;

// 赋值
for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++) cin >> a[i][j];
}

// 判断
// 第一行:[1,1] [1,2] [1,3] [1,4]
// 第二行:[2,1] [2,2] [2,3] [2,4]
// 第三行:[3,1] [3,2] [3,3] [3,4]
// 第四行:[4,1] [4,2] [4,3] [4,4]

// 已知第一行,末行,第一列,末列不存在靶心,去除减少循环次数
for(int i=2;i<=n-1;i++){
    for(int j=2;j<=m-1;j++){
        //将上下左右相邻的判断一下
        if (a[i][j] > a[i-1][j] && a[i][j] > a[i][j-1] && a[i][j] > a[i][j+1] && a[i][j] > a[i+1][j])
            cout << a[i][j] << endl;
    }
}

91. P5731.蛇形方阵

主讲老师 - 姚俞坚

1. 代码详解

int n, a[10][10] = {0};
cin >> n;

// 假设n=4
// a[1,1] a[1,2] a[1,3] a[1,4]
// a[2,1] a[2,2] a[2,3] a[2,4]
// a[3,1] a[3,2] a[3,3] a[3,4]
// a[4,1] a[4,2] a[4,3] a[4,4]


// 初始化行和列,
int i = 0, j = 0;
// 假设n=4,则执行16次,累加可以在循环体执行
for(int z=1;z<=n*n;){
    // 朝右
    i++;j++;
    while(j <= n && !a[i][j]){
        a[i][j] = z;
        j++;z++;
    }
    // 朝下,i下移一位,j左移一位,保证不越界
    i++;j--;
    while(i <= n && !a[i][j]){
        a[i][j] = z;
        i++;z++;
    }
    // 朝左,i上移一位,j左移一位
    i--;j--;
    while(j >= 1 && !a[i][j]){
        a[i][j] = z;
        j--;z++;
    }
    // 朝上,j右移一位
    i--;j++;
    while(i >= 1 && !a[i][j]){
        a[i][j] = z;
        i--;z++;
    }
}

for(int i=1;i<=n;i++){
    for(int j=1;j<=n;j++){
        printf("%3d", a[i][j]);
    }
    printf("\n");
}

92. P5732.杨辉三角

主讲老师 - 姚俞坚

1. 代码详解

// 杨辉三角形特性
// 1.第一行只有数字:1
// 2.每一行头尾数字:1
// 3.每一个非头尾数字是上一行对应左右的和:
//   比如a[5][3] = a[4][2] + a[4][3]
// 4.第n行数字的和为:2的n-1次方
//	 1+5+10+10+5+1=32  为: 2 x 2 x 2 x 2 x 2 = 32

//             1
//           1   1
//        1    2   1
//     1    3    3   1
//   1   4    6    4   1
// 1   5   10   10   5   1

// 为了方便观察,改为以上图形,程序上不需要考虑左边空隙

int n, a[21][21] = {0};
cin >> n;

// 初始首行
a[1][1] = 1;

// 循环
for(int i=2;i<=n;i++){
    // 每一行的列数正好是当前的i数
    for(int j=1;j<=i;j++){
        a[i][j] = a[i-1][j-1] + a[i-1][j];
    }
}

// 输出
for(int i=1;i<=n;i++){
    for(int j=1;j<=i;j++){
        cout << a[i][j] << " ";
    }
    cout << endl;
}

93. P5728.旗鼓相当的对手

主讲老师 - 姚俞坚

1. 代码详解

int n, a[1001][4] = {0}, cnt = 0;
cin >> n;

// 将学生成绩赋值
for(int i=1;i<=n;i++) cin >> a[i][1] >> a[i][2] >> a[i][3];

// 用之前学习过的对比法
// 90 90 90
// 85 95 90
// 80 100 91
// 第一第二行对比90和85差距<=5,90和95差距<=5,90和90差距<=5
// 第一第三行对比...
// 第二第三行对比... 直到所有同学之间对比过
// 求所有成绩小于5的对数,比如有两个人对比过成立就是1对

// 外层循环所有学生i=1表第一行学生成绩
// 3个学生对比的话,1,2比,1,3比 2,3比,不会用到3,则n-1
for(int i=1;i<=n-1;i++){
    // 内层循环从第二个学生开始:即i+1,+1了,次数n-1
    for(int j=i+1;j<=n;j++){
        // 检查正确性
        //printf("%d-%d-%d:%d-%d-%d\n", a[i][1], a[i][2], a[i][3], a[j][1]...);

        // 标记
        bool flag = true;
        // 求成绩对比是否小于<=5
        for(int z=1;z<=3;z++){
            // 差<=5
            if (a[i][z] < a[j][z]) {
                if (a[j][z] - a[i][z] > 5) {
                    flag = false; 
                    break;
                }	
            } else {
                if (a[i][z] - a[j][z] > 5) {
                    flag = false; 
                    break;
                }
            }
        }

        // 判断flag
        if (!flag) continue;

        // 继续判断和差<=10
        int x = a[i][1] + a[i][2] + a[i][3];
        int y = a[j][1] + a[j][2] + a[j][3];

        if (x < y) {
            if (y - x > 10) continue;
        } else {
            if (x - y > 10) continue;
        }

        // 能走到这里,就累加
        cnt++;
    }
}

// 输出
cout << cnt;

94. P2615.NOIP2015.提高组.神奇的幻方

主讲老师 - 姚俞坚

1. 代码详解

int n, a[40][40] = {0};
cin >> n;

// 样例:3 x 3
// 8 1 6
// 3 5 7
// 4 9 2


// 初始第一次二维下标位置,在第一行中间:n/2+1
int x = 1, y = n / 2 + 1;
// 初始第一个值
a[x][y] = 1;

// 假设n=3
for(int i=2;i<=n*n;i++){
    if (x == 1 && y != n) {
        // 帮助理解的假设推导3x3
        // 1.若(i-1)的值在第一行不在最后一列,只有8和1,反推i为9和2
        // 2.将i填入最后一列,9和2填入最后一行
        // 3.(i-1)所在列的右一侧,也就是8或1所在列右一侧9(3,2),2(3,3)

        // y当前为非n,推导在i-1的右一侧,即+1
        y++;
        // x当前为1,移到最后一行n
        x = n;
    } else if (x != 1 && y == n) {		
        // 1.若(i-1)在最后一列但不在第一行,7和2
        // 2.将i填入第一列,即将8和3填入第一列
        // 3.(i-1)所在行的上一行

        // x为非1,即不在第一行,即x-1
        x--;
        // y为n,调整到第一列,即y=1
        y = 1;
    } else if (x == 1 && y == n) {		
        // 1.若(i-1)在第一行最后一列,就是6
        // 2.将i写入(i-1)的正下方,7写入(2,3)

        // 正下方的行,x+1
        x++;
        // 列没动,不写
    } else if (x != 1 && y != n) {		
        // 1.若(i-1)不在第一行也不在最后一列:3,5,4,9
        // 2.若(i-1)的右上方未填数,将i填入(i-1)位置的右上方
        // 3.若填了数,则在正下方填入

        // 判断(i-1)右上方是否为0,x-1 y+1 表示右上方
        if (a[x-1][y+1] == 0) {
            x--;
            y++;
        } else {
            // 正下方
            x++;
        }

    }

    // 统一赋值
    a[x][y] = i;

}

// 输出
for(int i=1;i<=n;i++){
    for(int j=1;j<=n;j++){
        cout << a[i][j] << " "; 
    }
    cout << endl;
}

95. P5729.工艺品制作

主讲老师 - 姚俞坚

1. 代码详解

// 三维
int a[21][21][21] = {0}, w, x, h, q, ans = 0;

// 输入 长宽高
cin >> w >> x >> h >> q;

// 被激光切割的组数q
while(q--){
    int x1, y1, z1, x2, y2, z2;
    cin >> x1 >> y1 >> z1 >> x2 >> y2 >> z2;
    // 三重循环标记被切割的方块
    for(int i=x1;i<=x2;i++){
        for(int j=y1;j<=y2;j++){
            for(int k=z1;k<=z2;k++){
                a[i][j][k] = 1;
            }
        }
    }
}


// 输出三维,求0的个数,即为剩下的方块体积
for(int i=1;i<=w;i++){
    for(int j=1;j<=x;j++){
        for(int k=1;k<=h;k++){
            if (a[i][j][k] == 0) ans++;
        }
    }
}

cout << ans;

96. 函数.参数.返回值.常量

主讲老师 - 姚俞坚

1. 自定义函数

函数或叫自定义函数,是用户自己定义的一种函数,适用于将大量重复的代码进行封装调用

  • 自定义函数说明:

    • 每个程序都在用函数,比如 int main() 这是主函数,程序在这里自动执行;
    • int main() 中, int是返回类型,自然也会有其它类型,甚至无返回类型void;
    • 函数末尾除了void类型,一般都会有一个return 返回对应类型;
    • 函数名也遵循变量原则;
    • 用户自定义创建的函数,无法像主函数 main() 那样自动执行,需要被调用自行;
    // 创建一个无返回值的自定义函数,通过调用执行
    // 比如重复输出10组星号三角形
    
    // 星号三角
    void star() {
    	for(int i=1;i<=3;i++){
    		for(int j=1;j<=i;j++){
    			cout << "*";
    		}
    		cout << endl;
    	}
    }
    
    int main() {
    	for(int i=1;i<=10;i++){
    		star();
    	}
    	
    	return 0;
    }
    

2. 参数和返回值

函数中有两个重要的概念:参数和返回值,用于更加灵活的使用函数;

  • 参数:

    • 形参(形式参数),在定义函数时定义的变量(类似变量声明,可直接赋值作为初始值);
    • 实参(实际参数),在调用函数时传递的值(类似赋值,直接给形参变量赋值);
    • 定义了形参,实参需要一一对应传递赋值,否则出错;
    • 如果形参设置了默认值,则可以省略,一般定义默认值的形参在最后;
    • 有默认值的形参,如果被实参传递,则覆盖默认值;
    // 带参数的void类型函数
    // 控制输出的星数
    // num:每行个数
    // line:行数
    // def:显示的字符
    void star(int num, int line, string def = "*") {
    	for(int i=1;i<=line;i++){
    		for(int j=1;j<=num;j++){
    			cout << def;
    		}
    		cout << endl;
    	}
        // 特别注意:函数里声明的变量num,line,def,i,j在star函数体外无法识别
    }
    
    int main() {
    	// 调用,并传参
    	star(5, 5);
    	star(3, 3, "@");
    	
    	return 0;
    }
    
  • 返回值:

    • void 类型 是无返回值的,上面已经研究过;
    • 需要返回值的类型:比如 int 、float 、string 等;
    • 为什么要返回值?因为可以把函数当成一个变量,参与到主函数程序中的运算中;
    // 计算一个圆的面积和周长的和
    
    // 圆的面积:π * r * r
    float area(int r) {
    	float pi = 3.14;
    	return pi * r * r;
    }
    
    // 圆的周长:π * r * 2
    float circ(int r) {
    	float pi = 3.14;
    	return pi * r * 2;
    }
    
    int main() {
    	// 输入半径r
    	int r;
    	cin >> r;
    	
    	// 计算面积+周长的和
    	cout <<  area(r) + circ(r);
    	
    	return 0;
    }
    

3. 常量概念

之前一直在使用变量,即:可以改变的量;而常量是相对的产物,即:定义后就不可改变的量;

  • 常量:

    • 语法多种,推荐一种即可:const 类型 常量名 = 值;
      • const int A = 10; (这里的A为常量名,推荐用大写,以区别变量)
    • 常量是不可改变的量,定义之后无法再次赋值,所以定义时就必须初始化;
    • 为何要使用常量,有一些值是固定的,比如π,如果不小心改变了,语法上不报错就非常要命;
    • 为何要大写常量名,当一段程序有几十上百量时,常量变量识别度变差,故约定大写;
    // 创建一个常量PI
    const float PI = 3.14;
    
    // 圆的面积:π * r * r
    float area(int r) {
    	return PI * r * r;
    }
    
    // 圆的周长:π * r * 2
    float circ(int r) {
    	return PI * r * 2;
    }
    

97. 1512.甲乙的年龄

主讲老师 - 姚俞坚

1. 代码详解

// 1. 甲乙两者年龄只和是两位数
// 2. 这个两位数是一个质数
// 3. 这个质数(个位+十位=13)
// 4. 甲比乙大13

// 求甲乙分别是多少?

// 声明和变量
int sum = 0;

// 枚举(穷举)出所有情况
// 假设乙最小1,那么甲就是14,乙最大就是99-13=86
// 循环1-86之间,但当乙到达44时,和为101,也就是说43是头
for(int i=1;i<=43;i++){
    // 求和
    sum = i + (i + 13);
    //cout << i << " " << sum << endl;

    // 判断这个和是不是质数以及数字之和是13
    // 先用常规方法,然后改函数,第一次用函数会因缺少经验无从下手

    // 标记
    bool flag = true;
    // 判断质数,只能被1和本身整除
    for(int j=2;j<=sum-1;j++){
        if (sum % j == 0) {
            flag = false;
            break;
        }
    }

    // 标记判断
    if (flag == false) continue;
    //cout << i + 13 << " " << i << " " << sum << endl;

    // 判断数字之和13
    int a = sum / 10;
    int b = sum % 10;

    if (a + b == 13) {
        cout << i + 13 << " " << i << " " << endl;
    } 
}
// 判断质数
bool isZ(int n) {
	for(int j=2;j<=n-1;j++){
		if (n % j == 0) {
			// 只要执行了return 函数就终止执行
			return false;
		}
	}
	// 上面循环体没有执行return,就继续执行下面的return
	return true;
}

// 判断和
bool isS(int n) {
	int a = n / 10;
	int b = n % 10;
	
	// 执行了return true将终止往下执行
	if (a + b == 13) return true;
	
	// 没有执行true,则继续返回false
	return false;
}

int main() {
	int sum = 0;
	
	for(int i=1;i<=43;i++){
		sum = i + (i + 13);
		
		// 判断输出
		if (isZ(sum) && isS(sum))
			cout << i + 13 << " " << i << endl;
	}
	return 0;
}

98. 1862.友好数

主讲老师 - 姚俞坚

1. 代码详解

// 求约数和
int sum(int n) {
	int tmp = 0;
	// 1到n-1,题目说除了本身
	for(int i=1;i<=n-1;i++){
		if (n % i == 0) tmp += i;
	}
	return tmp;
}

int main() {
	int a, b;
	cin >> a >> b;
	
	//if ((对a求约数和) == b && (对b求约数和) == a)
	if (sum(a) == b && sum(b) == a) cout << "yes";
	else cout << "no";
	
	return 0;
}

99. P5737.闰年展示

主讲老师 - 姚俞坚

1. 代码详解

// 之前学习过除了函数的变量作用域
// 1. 我们可以意识到:函数体内的变量,其它函数或外部全局都无法识别
// 2. 外部全局声明的变量,叫做全局变量,所有区域均可识别
// 3. 当然,至于全局和局部变量重名会怎样,可自行测试,建议别重名

// 在和main等函数同一平级声明的变量为全局变量
// 我们要创建一个全局计数器变量cnt;
int cnt = 0, a[1500];

// 判断闰年函数
void isR(int year) {
	if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
		//cnt++;
		//cout << year << endl;
		// 这里的顺序是a[cnt] = year, 然后cnt++
		a[cnt++] = year;
	}
}

int main() {
	// 题目非常初级,主要学习下函数,实际答题中并不强制
	int x, y;
	cin >> x >> y;
	
	// 循环
	for(int i=x;i<=y;i++){
		// 判断闰年,将判断的方式作为函数处理
		// 它需要判断后输出,或者不输出,可以用void类型,否则还需要返回判断
		isR(i);
	}
	
	cout << cnt << endl;
	// 输出
	for(int i=0;i<cnt;i++){
		cout << a[i] << " ";
	}
	
	return 0;
}

100. P5739.计算阶乘.递归入门

主讲老师 - 姚俞坚

1. 代码详解

fn(n)
fn(n-1)
fn(n-2)
fn(n-3)
fn(直到1)
// 什么是递归?即:通过函数自我执行的方式表现出循环的效果
// 求n!,也就是阶乘,之前做过,这次作为递归入门
// 之前用循环做的,如下:
// i = 1, 1
// i = 2, 1 x 2
// i = 3, 1 x 2 x 3
// i = 4, 1 x 2 x 3 x 4
// i = n, 1 x ... x n


// fn
int fn(int n) {
	// 假设n=4,然后递减循环 4 3 2 1
	// 递归则不需要再循环
	// 递归思维:n x (n - 1) x (n - 2) x (n - 3) ...
	
	// 理 解:return n * fn(n - 1);
	// 调 用:fn(4)
	// 第一轮:return 4 * fn(3),fn(3)又调用了自己,就进入第二轮
	//			 		 fn(3)这块本身是:return 3 * fn(n-1) 也就是:3 * fn(2)
	
	// 第二轮:return 4 * 3 * fn(2)
	// 第三轮:return 4 * 3 * 2 * fn(1)  1到头了,单独判断返回1即可
	// ...
	// 最终轮:fn(1),判断if n == 1 return 1即可,最终为:return 4 * 3 * 2 * 1
	
	
	// 先判断1停止递归
	if (n == 1) return 1;
	
	// 递归
	return n * fn(n - 1);
}

int main() {
	int n;
	cin >> n;
	
	// 递归求n!
	cout << fn(n);
	return 0;
}

101. 1514.数根

主讲老师 - 姚俞坚

1. 代码详解

// 树根
int fn(int n) {
	int sum = 0;
	// 短除
	while(n != 0){
		sum += n % 10;
		n /= 10;
	}
	
	// 判断sum是否是个位数
	if (sum < 10) return sum;
	
	// 递归
	return fn(sum);
}

int main() {
	int n;
	cin >> n;
	
	// 调用函数
	cout << fn(n);
	return 0;
}

102. 1223.汉诺塔的移动次数

主讲老师 - 姚俞坚

1. 代码详解

image-20240125161802209
// 1. 移动只能一块一块移动
// 2. 大的不能放到小的上面
// 3. 最终状态从A到C状态,如上图

// 手动计步如下:
// 1块:1步
// 2块:3步
// 3块:7步
// 4块:15步

// 要求输入n块,<= 20,求多少步
// 已知n == 1,那么就 1 步
// 假设n == 2,先将小块移动到B,花了1步,大块移动到C花了1步,小块再移动到C;
//  		  结论:小块2步 + 大块1步 = 3步

// 假设n == 3,先将小块移动到C,花了1步,中块移动到B,花了1步,小块移动到B,花了2步
//			  大块移动到C,花了1步,小块移动到A,花了3步,中块移动到C,花了2步
//			  小块移动到C,花了4步
//			  结论:小块4步 + 中块2步 + 大块1步 = 7步

// 假设n == 4,结论:8 + 4 + 2 + 1 = 15,找到规律:每次都是x2的步数,也就是2的n次方-1
// 用这种规律直接:2 * 2 * 2 * 2 - 1 = 15 步;

// 非常有意思的事,深入研究规律后,直接循环做出来了。根本无需递归
int n;
cin >> n;

int step = 1;
// 输出
for(int i=1;i<=n;i++){
    step *= 2; 
}

cout << step - 1;

// 那我们再思考用递归来做一下:
// 步数:n = 1, 2, 3, 4  步 = 1, 3, 7, 15
// 公式:2 * fn(n - 1) + 1,fn(n - 1)是上一层,x 2 + 1 = 本层步数
// 代码:return 2 * fn(n - 1) + 1,方便理解,列出轮次:
// 第一轮:return 2 * fn(3) + 1
// 第二轮:return 2 * (2 * fn(2) + 1) + 1
// 第三轮:return 2 * (2 * (2 * fn(1) + 1) + 1) + 1
// 第四轮:return 2 * (2 * (2 * 1 + 1) + 1) + 1 = 15

// 汉诺塔
int fn(int n) {
	// n == 1
	if (n == 1) return 1;
	
	return 2 * fn(n - 1) + 1;
}

int main() {
	int n;
	cin >> n;
	
	cout << fn(n);
	return 0;
}

103. P5743.猴子吃桃

主讲老师 - 姚俞坚

1. 代码详解

// 1. 每一天吃当前数量的一半+1个
// 2. 第n天发现只剩1个
// 3. 求共多少个

// 假设n == 4,剩1个
// 没有思路就先猜,第3天,大概是4个,吃一半加1个,正好剩1个,这个很容易猜到;
// 但我们可能要cin >> n,fn(n);输入4,不可能判断n == 4 return 1;
// 但我们知道n == 1是第一天,我们要反向思考这题:
// 原本:1:22  2:10  3:4  4:1  从后向前推:(当前 + 1) * 2
// 反向:1:1   2:4   3:10 4:22 
// 换成递归格式为:return (fn(n-1) + 1) * 2,并且 n == 1 return 1;
// 轮次列表:
// 第一轮:return (fn(3) + 1) * 2
// 第二轮:return (((fn(2) + 1) * 2) + 1) * 2
// 第三轮:return (((((fn(1) + 1) * 2) + 1) * 2) + 1) * 2
// 第四轮:return (((((1 + 1) * 2) + 1) * 2) + 1) * 2 = 22

// 猴子吃桃
int fn(int n) {
	// 界限
	if (n == 1) return 1;
	
	// 逆推
	return (fn(n-1) + 1) * 2;
}

int main() {
	int n;
	cin >> n;
	
	// 递归
	cout << fn(n);
	return 0;
}

104. 1148.数数小木块

主讲老师 - 姚俞坚

1. 代码详解

// 先硬算,然后找规律
// n:块数
// 1:1  2:3  3:6  4:10  5:15  
// 1:1
// 2:1+2
// 3:1+2+3
// 4:1+2+3+4
// 5:1+2+3+4+5

// 方块
int fn(int n) {
	// 界限
	if (n == 1) return 1;
	
	// 上一层的个数 + 本层多出来的 = 本层个数
	return fn(n - 1) + n;
}

int main() {
	int n, sum = 0;
	cin >> n;
	
	// 题目要求将所有层数将每一层累加
	for(int i=1;i<=n;i++){
		sum += fn(i);
	}
	cout << sum;
	return 0;
}

105. 1335.土地分割

主讲老师 - 姚俞坚

1. 代码详解

// 数据范围:10的18次方= 1000000000000000000
// int取值范围:-2147483648~2147483647 (10的10次方)
// long long取值范围 9223372036854775808~+9223372036854775807 (10的19次方)
// 故这里取long long 长整型


// 分割,求最大公约数
long long fn(long long m, long long n) {
	// 辗转相除法->欧几里得算法
	// 算法:
	// 		1. 如果m % n == 0,那么n是最大数公约数,比如 8 % 4 == 0,4 就是
	//		2. 如果m % n != 0,假设:m = 15 n = 12,将12交给m,将15%12余数交给n
	//		3. 递归直到 == 0;
	
	// 求余判断
	if (m % n == 0) {
		return n;
	} else {
		return fn(n, m % n);
	}
}

int main() {
	long long m, n;
	cin >> m >>n;
	
	// 求值
	cout << fn(m, n);
	return 0;
}

106. 常用内置函数

主讲老师 - 姚俞坚

1. 数学函数

#include <iostream>
#include <cmath>		// 数序函数库 或math.h
using namespace std;

int main() {
	// 绝对值
	cout << abs(-5) << endl;
	// 向上取整,有小数进一位,5.11=6
	cout << ceil(5.11) << endl;
	// 向下取整,截断取,5.95=5
	cout << floor(5.95) << endl;
    // 四舍五入
    cout << round(5.55) << endl;
	// 平方根
	cout << sqrt(16) << endl;
	// 幂函数,10的4次方的值
	cout << pow(10, 4) << endl;
	// 自然常数e为:2.71828...
	// exp(n)为指数函数,获取e的n次方,1次方即自己
	cout << exp(1) << endl;
	// 对数函数log(n),即幂的逆运算
	// 获取以e为底的n的对数
	cout << log(exp(3)) << endl;
	
	// 还有sin(正弦)、cos(余弦)、tan(正切)启蒙涉及不到
	
	
	return 0;
}

2. 比较函数

// 取最小值
cout << min(1, 9) << endl;
// 取最大值
cout << max(1, 9) << endl;

107. P5735.距离函数

主讲老师 - 姚俞坚

1. 代码详解

// 用函数减少重复
float dis(float a, float b, float c, float d) {
	return sqrt((a - b) * (a - b) + (c - d) * (c - d));
}

int main() {
	float x1, x2, x3, y1, y2, y3, sum = 0;
	cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
	
	// 两点距离:
	sum += dis(x2, x1, y2, y1);
	sum += dis(x3, x2, y3, y2);
	sum += dis(x3, x1, y3, y1);
	
	// 输出
	printf("%.2f", sum);
	
	return 0;
}

108. 1253.寻找肇事司机

主讲老师 - 姚俞坚

1. 代码详解

#include <iostream>
#include <math.h>
using namespace std;

int main() {
	int a, b, c, d;
	// 循环四位数
	for(int i=1100;i<=9988;i++){
		a = i / 1000;
		b = i / 100 % 10;
		c = i / 10 % 10;
		d = i % 10;
		
		
		
		// 判断
        // 四位的车号刚好是一个整数的平方
		// sqrt(16) = 4,怎么判断4的平方是16
		// sqrt(26) = 5.xxx  sqrt(25) = 5
		// 4 x 4 = sqrt(16) * sqrt(16)
		// floor(sqrt(26)) = 5  ?= sqrt(26) = 5.xxx
		if (a == b && c == d && a != c && sqrt(i) == floor(sqrt(i))) {
			cout << i << endl;
		}
	}
	return 0;
}

109. P5736.质数筛

主讲老师 - 姚俞坚

1. 代码详解

// 判断质数
bool isP(int x) {
	// 1不是质数,直接返回0。
	if (x == 1) return 0;
	// 循环验证质数,1和本身不参数,2~x-1
	// for(int i=2;i<=x-1;i++)
	// 优化算法:
	// 			1.假设x = 16,它不是质数,因子有:2, 4, 4, 8 
	//			2.假设x = 20,它不是质数,因子有:2, 4, 5, 10
	// 			3.假设x = 30,它不是质数,因子有:2, 3, 5, 6, 10, 15
	// 寻找规律:
	//			1.这些因子的最大值,基本是数值的一半,i<=x/2即可;
	//			2.这些因子中间来一刀,左右两侧是配对的。比如x=30,只要循环到5-6之间即可,sqrt(30)
	
	// 循环验证
	for(int i=2;i<=sqrt(x);i++){
		if (x % i == 0) return false;
	}
	return true;
}

int main() {
	int n;
	cin >> n;
	
	// 循环1-n赋值
	for(int i=1;i<=n;i++) {
		// 题目要求存入数组,本题其实没必要,它只能检测结果,不能检测你代码
		int tmp;
		cin >> tmp;
	
		if (isP(tmp)) cout << tmp << " ";
	}
	
	return 0;
}

110. P5738.歌唱比赛

主讲老师 - 姚俞坚

1. 代码详解

// 计算每个学生的得分
float score(int x[], int m) {
	int minn = 11, maxn = -1, sum = 0;
	// 遍历数组x
	for(int i=1;i<=m;i++){
		// 大小
		minn = min(x[i], minn);
		maxn = max(x[i], maxn);
		// 累加
		sum += x[i];
	}
	
	return float(sum - minn - maxn) / (m - 2);
}


int main() {
	int n, m, a[21];
	float maxn = -1;
	cin >> n >> m;
	
	// 外层循环选手
	for(int i=1;i<=n;i++){
		// 内层循环分数,并赋值
		for(int j=1;j<=m;j++) cin >> a[j];

		// 将每个学员的分数组传给函数处理返回平均分
		maxn = max(maxn, score(a, m));
	}
	
	// 输出
	printf("%.2f", maxn);

	return 0;
}

111. 字符与ASCII码

主讲老师 - 姚俞坚

1. 字符

字符类型,即:char 类型C 风格字符串,可以存储字符或字符串的类型;

  • 字符类型说明:

    • 强调一下:char 类型 不是 string,string是声明的字符串,可以放一串字符;而char,只能放一个;

      • 例:char a = ‘A’ , 1. 只能存一个字符; 2. 必须是单引号包含;
    • 如何表示字符串?可以用字符数组来表示:

      • char a[5] = “hello”; 1. 这是错的,需要预留一位存储\0(空字符null)来表示结束 ;
      • char a[6] = “hello”; 2. 这是对的,此时可以用双引号来表示字符串;
      • cout << a; 3. 直接输出即可,无须数组式的循环逐个输出;
      a[0]a[1]a[2]a[3]a[4]a[5]
      hello\0
      //char a = 'A';
      //cout << a;
      
      // 5位不够,需要预留一位存储\0(空字符null)来表示结束
      char a[6] = "hello";
      cout << a;
      
    • 初始化声明方法和普通数组差不多:

      // 初始化字符数组
      char a[6];
      // 初始化并直接赋值
      char b[6] = {"hello"};
      // 初始化并赋值初始值
      char c[6] = {0};
      
      // 动态初始
      char d[] = {"world"};
      

2. ASCII码

ASCII码,即:美国标准信息交换代码;用于和计算机数据通信;

  • 码表:
img

  • 通过上述表查阅到:小写a的十进制编码为97,然后逐步递增。大写的A是65,往后逐步递增;

  • 什么是十进制,ASCII码到底如何和计算机通信,解决了啥问题?自己百度查阅,我们只关注答题啊;

    // 字符型a
    char a = 'a';
    // 输出它的十进制,即整型数值
    cout << int(a);
    
    // 整型数值65
    int b = 65;
    // 输出它的字符
    cout << char(b);
    

112. 1971.大小写转换

主讲老师 - 姚俞坚

1. 代码详解

char a;
cin >> a;

// 查表:a 97,A 65 梳理两点:
// 1. a跑到A,a - 32 = 65
// 2. A跑到a,A + 32 = 97

// 是否需要转换整数后判断?答:不需要
// 直接字符判断即可,它底层会自行转换判断
// 直接判断>='A',意味>=97,得到大写的范围
if (a >= 'A' && a <= 'Z') {
    a += 32;
} else {
    a -= 32;
}

// 输出a
cout << a;

113. P5733.自动修正

主讲老师 - 姚俞坚

1. 代码详解

char a[110] = {0};
cin >> a;

// 1. 小写变大写,其它不变
// 2. 如果本身是大写,则不变
// 3. 如果是数字和符号,则不变

// 怎么循环去判断是否要大写?
// 可以判断字符数组最后一位是'\0'结束
// cout << a[0]; 从0开始填入字符的
// 死循环
int cnt = 0;
while(1){
    // 遇到结尾就退出
    if (a[cnt] == '\0') break;
    // 判断是小写
    if (a[cnt] >= 'a' && a[cnt] <= 'z') a[cnt] -= 32;
    // 累加
    cnt++;
}

// 输出
cout << a;

114. P1914.小书童.凯撒密码

主讲老师 - 姚俞坚

1. 代码详解

char a[60] = {0};
int n;
cin >> n;
cin >> a;

// 上节课用while结合\0 break,这次用for
// 注意:字符数组从0开始,条件虽然也可以死循环,但也可以直接判断
// for(int i=0;a[i]!='\0';i++) 直接判断不等于结尾就一直循环
// 当然,还可以简化,直接 a[i] 也行,因为 \0 和 0 一样,表示false
for(int i=0;a[i];i++){
    // 假设n=1,xyz = yz{,缺少越界判断
    // cout << char(int(a[i]) + n);

    int tmp = int(a[i]);

    // a 97 z 122
    // 假设 n 10, y 121 + 10 = 131, 131 - 122 + 97 - 1即可
    if (tmp + n > 122) {
        cout << char(tmp + n - 122 + 97 - 1);
    } else {
        cout << char(tmp + n);
    }
}

115. cstring头和字符函数

主讲老师 - 姚俞坚

1. sizeof操作符

字符数组是如何获取它的长度,比如占用多少,或者有多少个字符?之前的题目,都只是判断\0结束

  • sizeof:

    • 它可以返回一个字符数组所占的内存字节数(字节数理解为:数组分配的一个个小格子)

    • 比如 : char a[10] = “hello” , 它占用了多少?

      // 占用10个字节,{"hello"} 和 {'h','e','l','l','o'}; 都一样
      char a[10] = "hello";
      cout << sizeof(a);
      
      // 占用6个字节,不定式,末尾\0占一个
      char a[] = "hello";
      cout << sizeof(a);
      
    • 所以,想用 sizeof 操作符 来 获取字符个数,其实并不方便。当然,用 a[] 这种 ,然后 - 1也可以。

2. cstring头

cstring是 C 标准库头文件, 包含了一些 C 风格字符串的类型和函数;

  • 基本使用:

    • 首先要引入 cstring : #include

      #include <iostream>
      #include <cstring>
      using namespace std;
      
    • 使用 strlen() 函数 来获取 字符数组的长度:

      // cstring下的strlen函数获取
      // 并不会统计占用,也不会统计结束符
      // 结果为:5
      char a[10] = "hello";
      cout << strlen(a);
      
    • 使用 strcpy()strncpy() 函数赋值字符数组:

      // 无法直接复制
      // char b[20] = a;
      // cout << b;
      
      // strcpy复制字符数组
      char b[20];
      strcpy(b, a);
      cout << b;
      
      // strncpy复制指定个数
      char c[20];
      strncpy(c, a, 3);
      cout << c;
      
    • 使用 strcat()strncat() 函数,连接字符数组:

      // 连接两个字符数组
      char a[20] = "hello";
      char b[10] = ", world!";
      // 函数本身会返回连接后的字符串
      // 参数1:被添加的字符数组;
      // 参数2:添加的字符数组;
      cout << strcat(a, b) << endl;
      // a被添加了,所以它增加了字符
      cout << a << endl;
      // b不变
      cout << b << endl;
      
      // 连接部分字符数组
      char a[20] = "hello";
      char b[10] = ", world!";
      cout << strncat(a, b, 5) << endl;
      cout << a << endl;
      cout << b << endl;
      
    • 使用 strchr()strstr() 函数,来实现字符数组查找:

      // 查找字符在数组中的位置
      char a[20] = "hello, world!";
      // 获取第一次查询到的字符位置,并往后输出字符
      cout << strchr(a, 'o');
      // 获取到底是第几个位置
      cout << strchr(a, 'o') - a + 1;
      
      
      // 查询一串字符在数组中的位置
      char a[20] = "hello, world!";
      cout << strstr(a, "or");
      cout << strstr(a, "or") - a + 1;
      
    • 更多 cstring 旗下的函数:https://www.apiref.com/cpp-zh/cpp/header/cstring.html

116. 1478.出现次数最多的小写字母

主讲老师 - 姚俞坚

1. 代码详解

char s[110];
int a[130] = {0};
cin >> s;

// 循环输入的字符
// 获取长度,strlen返回的是size_t(无符号整型),用int转换
for(int i=0;i<=int(strlen(s));i++){
    // 转换成ascii,移位到数组初始,并累计
    a[int(s[i])]++;
}

// 假设a最大
int maxn = 97;
// 输出字母的ascii次数
for(int i=98;i<=122;i++){
    // 比大小,注意这里必须有等于,方便将ascii码大的交给maxn
    if (a[maxn] <= a[i]) maxn = i;
}

// 输出
cout << char(maxn);

117. 1116.调换位置

主讲老师 - 姚俞坚

1. 代码详解

char s[110];
cin >> s;

// 获取字符总长度
int len = strlen(s);
// 获取逗号所处的位置
int index = strchr(s, ',') - s + 1;

// 循环输出
for(int i=index;i<=len-1;i++) cout << s[i];

// 输出逗号
cout << ',';

// 复制逗号左的字符
char left[len] = {0};
strncpy(left, s, index - 1);
cout << left;

118. P1125.NOIP2008.提高组.笨小猴

主讲老师 - 姚俞坚

1. 代码详解

char s[110];
int a[30] = {0};	// 从0开始存储a-z
cin >> s;

// 求出s长度
int len = strlen(s);

// 	最大最小值
int maxn = -1, minn = len;

// 循环97-122
// 或者0-25,用当前字母的ascii-97或-'a'即可
// cout << 98 - 'a'; 相当于98 - 97
for(int i=0;i<=len-1;i++){
    a[s[i] - 'a']++;
}

// 求最大值和最小值
for(int i=0;i<=25;i++){
    if (a[i] != 0) {
        maxn = max(maxn, a[i]);
        minn = min(minn, a[i]);
    }
}

// 判断质数
int d = maxn - minn;
// 特殊
if (d == 0 || d == 1) {
    cout << "No Answer" << endl;
    cout << 0;
    return 0;
}

// 循环
for(int i=2;i<=sqrt(d);i++){
    if (d % i == 0) {
        cout << "No Answer" << endl;
        cout << 0;
        return 0;
    }
}

// 输出结果
cout << "Lucky Word" << endl;
cout << maxn - minn;

119. 1134.国王的魔镜

主讲老师 - 姚俞坚

1. 代码详解

// 判断是否回文
bool isHW(char x[]) {
    int len = strlen(x);

    // 情况1:回文必须是偶数
    if (len % 2 != 0) return false;

    // 情况2:必须是回文
    // 假设传过来的是: ABBA,判断03、12是否相等
    // 假设传过来的是: ABBAABBA,判断07、16、25...是否相等
    for(int i=0;i<=len/2-1;i++){
        if (x[i] != x[len - 1 - i]) return false;
    }
    return true;
}


int main() {
    char s[110];
    cin >> s;

    // 截取一半,如果用strcpy也行,但需要另外创建一个字符数组变量
    // 此方法,给一半后面位置强行改为0,表示结束了
    // s[len / 2] = '\0';
    // cout << s;

    // 截取后的字符数组
    // 循环判断是不是回文:即倒过来也一样
    while(isHW(s)){
        s[strlen(s) / 2] = '\0';
    }

    // 输出最终长度
    cout << strlen(s);

    return 0;
}

120. string字符串.常用函数

主讲老师 - 姚俞坚

1. string

string是标准模板库 STL 中提供处理字符串的工具类型,可以直接赋值使用,无须设置数组;

  • 字符串类型:

    • 可以直接赋值,无须数组化,但本身又是数组;

    • string是弹性长度,根据你赋值的内容自动伸缩,无须考虑赋值越界问题;

      // 字符串需双引号
      string s = "hello!";
      cout << s;
      
      // string本身也是数组
      cout << s[0];
      cout << s[3];
      cout << s[5];
      

2. 常用函数

字符串类型,有非常多的实用函数工具,这里把最最常用的罗列出来,后续课程逐步补充

  • 首先,字符串类型 string 本质是一个类(和之前的类型有所区别),它函数语法是类形式的语法:

    • 语法结构为:字符串变量.函数() ,这里的 函数(),我个人喜欢读成 方法();
    • 也就是:字符串变量.方法() ,在使用这些方法时,需要 include
    • 当然,我这里使用如下方法并没有引入 也可以使用,可见已被隐式引入;
    // 字符串
    string s = "hello";
    
    // 获取字符串长度size()或length()方法
    cout << s.size();
    cout << s.length();
    cout << s.max_size();	// 获取最大字符数
    
    // 拼接方法append(),在s后面添加字符串
    s.append(", world!"); 
    cout << s;
    
    // 拼接字符串,直接用+号也能实现
    s += ", world!"; 
    cout << s;
    
    // 插入字符(一个),push_back()末尾插入
    s.push_back('a');	// 一个字符单引号
    cout << s;
    
    // 指定位置插入字符或字符串:insert()
    s.insert(3, "@@@");		// 字符串形式,两个参数:位置和字符串
    cout << s;
    s.insert(3, 4, '#');	// 字符形式,三个参数:位置、个数、单个字符
    cout << s;
    
    // 查找字符串中是否包含某个字符:find()
    // 不存在返回:-1,存在返回:位置
    cout << s.find("ll");			// 只有一个参数时
    
    // 参数2,从第几个位置查找,自然找不到,会返回一个超大的数
    // 超大数不好判断没找到,一般是最好返回-1
    // 但由于find()本身返回的是无符号整数,即:没有负数,所以无法返回-1
    // 直接用 int 转换下即可
    cout << int(s.find("ll", 3)) << endl;
    // 或赋值方案
    int index = s.find("11", 3);
    cout << index;
    
    // 字符串截取:substr
    cout << s.substr(2);		// 从第2个位置截取到最后
    cout << s.substr(2,2);		// 从第2个位置截取2个
    

121. string.char.int的相互转换

主讲老师 - 姚俞坚

1. char转int

其它现代语言数据类型转换都比较方便,而C++这种语言机制导致转换起来较为麻烦

  • char字符转int:

    // 先抛出问题:string数字转int,常规方法int转不了
    string x = "97";
    cout << x + 1;			// 语法错误,无法相加
    cout << int(x) + 1;		// 语法错误,无法转换
    
    
    // 字符 char转ascii码
    char y = 'a';
    cout << y;			// 输出字符a
    cout << int(y);		// 输出ascii码97,所以,用int转换char字符,只会得到ascii码
    
    // 字符数字 char转int
    char z = '8';
    cout << int(z);			// 输出的是56,得到的是ascii码
    cout << z - '0';		// 输出的是8,可以得到整型8	
    cout << z - '0' - 1;	// 输出的是7,为了验证是不是int,减1便知
    cout << atoi(&z);		// 输出的是8,&表示z变量的引用地址(指针),不用理解,记住语法即可
    
    // 关于指针和引用地址,会在后续课程中专门篇幅讲解(不是本套),目前都是有意避开,避不开的强记
    

2. string转int

将 string 转换成 int 的思路:就是先让 string 变成 char 的引用,然后用 atoi() 函数转换

  • string字符转int:

    // string转int
    string k = "123";
    // 先转换到char的指针,使用c_str()函数就是这个意思
    // 然后再用atoi函数包裹转成int
    cout << atoi(k.c_str()) + 1;  // 124
    
    // 当然还提供了直接转换的函数stoi
    string p = "456";
    cout << stoi(p);
    

122. 1130.简单a+b

主讲老师 - 姚俞坚

1. 代码详解

string s;
cin >> s;

// +号位置
int i = s.find("+");
// left
string a = s.substr(0, i);

// right 1+2=
string b = s.substr(i+1, s.length() - (i+1) - 1);

// 输出
cout << atoi(a.c_str()) + atoi(b.c_str()); 

123. 1114.趣味填空

主讲老师 - 姚俞坚

1. 代码详解

string s;
cin >> s;

int p = s.find("=");

// left
string a = s.substr(0, p);
// right
string b = s.substr(p+1);


// 假设1234,则有三种情况:123+4 12+34 1+234
for(int i=1;i<=p-1;i++){
    int x = stoi(a.substr(0, p-i));
    int y = stoi(a.substr(p-i));

    if (x + y == stoi(b)) {
        printf("%d+%d=%d", x, y, stoi(b));
        return 0;
    }
}

// 输出
cout << "Impossible!";

124. 读入一行.fgets.getline函数

主讲老师 - 姚俞坚

1. getline()函数

在读入字符串时,遇到换行和空格,它是认为下一次 cin 读入,这给我们编码带来一些麻烦

  • getline()读入一整行:

    // 先抛出问题,假设s1输入=> hello world!
    string s1;
    cin >> s1;
    cout << s1;		// 结果为hello,空格后的字符串会理解为下一次cin
    
    // scanf也不行
    string s2;
    scanf("%s", &s2);	// 直接报错,无法使用
    cout << s2;
    
    // scanf单字符输入
    char a;
    scanf("%c", &a);	// 单字符输入,不管输入多少,得到1个字符
    cout << a;
    
    // scanf字符数组输入,字符数组本身是引用地址,无须&前缀
    char s[10];
    scanf("%s", s);		// 输入多少,输出多少,可是遇到空格就没了
    cout << s;
    
    // getline(cin, str)  参数1:固定cin,参数2:输入的字符串变量
    // getline()函数 适用于 string类型
    string s;
    getline(cin, s);	// 输入 hello world!  不会被空格断掉
    cout << s;
    

2. fgets()函数

对于字符数组,我们可以采用 fgets() 函数读入一整行

  • fgets()读入一整行:

    // 字符数组s
    char s[20];
    // 参数1:要存储的字符数组
    // 参数2:限定最大读入长度,防止越界
    // 参数3:固定参数,表示标准输入
    fgets(s, sizeof(s), stdin);
    cout << s;
    
  • cin.getline()读入一整行:

    // 和fgets()函数类似
    char s[20];
    cin.getline(s, sizeof(s));
    cout << s;
    

125. P5015.NOIP2018.普及组.标题统计

主讲老师 - 姚俞坚

1. 代码详解

string s;
getline(cin, s);

int cnt = 0;
// 统计
for(int i=0;i<=(int)s.length()-1;i++){
    // string被拆分单字符,用单引号判断
    if (s[i] != ' ') cnt++;
}

cout << cnt;

126. 1012.我是第几个单词

主讲老师 - 姚俞坚

1. 代码详解

string s;
getline(cin, s);

string x;
getline(cin, x);

// 查找位置
int p = s.find(x);

// 判断
if (p == -1) {
    // 总长度
    int len =  s.length();
    // 去掉空格数
    for(int i=0;i<=(int)s.length()-1;i++){
        if (s[i] == ' ') len--;
    }
    // 去掉末尾点
    cout << len - 1;
}
else {
    int cnt = 0;
    // 计算到p的空格数
    for(int i=0;i<=p;i++){
        if (s[i] == ' ') cnt++;
    }
    // 三个空格,就是第四个单词
    cout << cnt + 1;
}

127. cctype判断.转换

主讲老师 - 姚俞坚

1. cctype头

本节课,学习一下 cctype 头,让我们更舒适的去判断数字、字母或其它值的判断

  • cctype 标准头:

    #include <cctype>		// 不同的版本,可能非必要导入
    
    char a = 'A';
    // isalpha() 判断一个字符是否是字母(a-zA-Z)
    cout << isalpha(a);		// 非字母返回0,小写字母返回2,大写返回1
    // isdigit() 判断一个字符是否是数字(0-9)
    cout << isdigit(a);		// 非数字返回0,数字返回1
    // isalnum() 判断一个字符是否是数字、字母(0-9a-zA-Z)
    cout << isalnum(a);		// 非返回0,数字4,小写2,大写1
    
    // islower() 判断小写字母(a-z)
    // isupper() 判断大写字母(A-Z)
    // ispunct() 判断标点符号
    // isspace() 判断空格、制表符、换行符
    // isblank() 判断空格、制表符
    
    
    // 转换大小写
    char b = 'A';
    cout << char(toupper(b));		// 转换成大写
    cout << char(tolower(b));		// 转换成小写
    

128. P1308.NOIP2011.普及组.统计单词数

主讲老师 - 姚俞坚

1. 代码详解

// 转成小写
string to_lower(string x) {
	// 先将字符全部转换成小写
	for(int i=0;i<=(int)x.length();i++){
		// 如果是大写字母,就转成小写
		if (isupper(x[i])) {
			x[i] = char(tolower(x[i]));
		}
	}
	
	return x;
}

int main() {
	string w, s;
	getline(cin, w);
	getline(cin, s);
	
	// 处理大小写
	w = to_lower(w);
	s = to_lower(s);
	
	// 单词而不是字符串,需要给单词前后加上空格
	w = " " + w + " ";
	s = " " + s + " ";
	
	// 判断是否找到
	int i = s.find(w);
	// 找不到直接-1
	if (i == -1) {
		cout << -1;
	} else {
		int cnt = 0;
		int f = i;		// 第一次出现的位置
		// 有多个单词,用while循环逐个找
		while(i != -1){
			cnt++;	// 找到一个就+1
			i = s.find(w, i + 1);  // 在i位置找到,就+1位置往后继续找
		}
		cout << cnt << " " << f;
	}
	
	return 0;
}

129. 1113.隐藏的最大整数

主讲老师 - 姚俞坚

1. 代码详解

string s;
cin >> s;

// 连续字符,初始空字符串
string num, maxn = "";
// 循环
for(int i=0;i<=(int)s.length()-1;i++){
    // 判断是否是数字
    if (isdigit(s[i])) {
        num += s[i];
    } else {
        // 把连续的数字字符比较后赋值给maxn
        if (num.length() > maxn.length()) maxn = num;
        // 清空
        num = "";
    }

}

// 输出位置
cout << s.find(maxn) + 1;

130. P1957.口算练习题

主讲老师 - 姚俞坚

1. 代码详解

int n, a, b;
char p = ' ';

// 这里需要\n,因为getline读取一行,会读取到换行符,导致漏行
scanf("%d\n", &n);

// 循环
for(int i=1;i<=n;i++){
    string s;
    getline(cin, s);

    // 判断字符第一位是否为数字
    if (isdigit(s[0])) {
        a = stoi(s);
        b = stoi(s.substr(s.find(" ") + 1));		
    } else {
        p = s[0];
        s = s.substr(2);
        a = stoi(s);
        b = stoi(s.substr(s.find(" ") + 1));
    }

    // 先将a和b,外加运算符长度得到
    int len = (to_string(a) + to_string(b)).length() + 2;

    // 运算
    switch (p) {
        case 'a':
            printf("%d+%d=%d\n", a, b, a+b);
            len += (to_string(a+b)).length();
            printf("%d\n", len);		
            break;
        case 'b':
            printf("%d-%d=%d\n", a, b, a-b);
            len += (to_string(a-b)).length();
            printf("%d\n", len);
            break;
        case 'c':
            printf("%d*%d=%d\n", a, b, a*b);
            len += (to_string(a*b)).length();
            printf("%d\n", len);
            break;
    }

}

131. 结构体概念入门

主讲老师 - 姚俞坚

1. 基本格式

结构体:即一组变量的聚合体,可以将非同类型的数据绑定成一体的这么个东西

  • 结构体语法:

    // 结构体类型创建,并对内部变量直接赋初始值
    struct info {
        string name = "王二狗";
    	int age = 15;
    	char gender = 'A';
    	float weight = 1.55;
        bool flag = true;
    };
    
    // 定义一个结构体变量:struct info a; 
    // 而struct可以省略,方便阅读,可以把info当成自定义类型
    info a;
    
    int main() {
    	// 调用结构体变量
    	cout << a.name << endl;
    	cout << a.age << endl;
    	cout << a.gender << endl;
    	cout << a.weight << endl;
        cout << a.flag << endl;
    	return 0;
    }
    
    // 初始化交给变量声明
    struct info {
    	char name[20];
    	int age;
    	char gender;
    	float weight;
        bool flag;
    };
    
    // 可以初始化{}
    info a = {};
    
    // 初始化0,需要把string改为char name[20],否则报错
    info a = {0};
    
    // 对标赋值
    info a = {"张三", 12, 'B', 1.38, true};
    
    // 还有一种结合在一起的写法
    struct info {
    	char name[20];
    	int age;
    	char gender;
    	float weight;
    	bool flag;
    } a = {"张三", 12, 'B', 1.38, true};
    

2. 数组

结构体数组:如果要实现多组结构体数组,和普通数据使用方法一样,结合结构体语法即可

  • 数组语法:

    struct grade {
    	string name;
    	int age;
    	char gender;
    };
    
    int main() {
    	// 不省略struct,提高可读性
    	struct grade s[3] = {{"张三", 15, 'A'}, {"李四", 14, 'B'}, {"王五", 13, 'A'}};
    	// 输出结构体数组第一条
    	cout << s[0].name << " " << s[0].age << " " << s[0].gender;
    	
    	return 0;
    }
    

132. P5744.培训

主讲老师 - 姚俞坚

1. 代码详解

// 学员信息
struct info {
	string name;
	int age;
	int score;
};

int main() {
	// 初始化结构体
	struct info stu[10];
	int n;
	cin >> n;
	
	// 赋值
	for(int i=1;i<=n;i++) cin >> stu[i].name >> stu[i].age >> stu[i].score;
	
	
	// 计算
	for(int i=1;i<=n;i++){
		// 年龄+1岁
		stu[i].age++;
		// 分数+20%,但不大于600分
		if (stu[i].score * 1.2 < 600) stu[i].score *= 1.2;
		else  stu[i].score = 600;
	}
	
	// 输出
	for(int i=1;i<=n;i++){
		cout << stu[i].name << " " << stu[i].age << " " << stu[i].score << endl;
	}
	
	return 0;
}

133. P5740.最厉害的学生

主讲老师 - 姚俞坚

1. 代码详解

struct info {
	char name[10];
	int chi;
	int mat;
	int en;
};

int main() {
	struct info stu[1010];
	int n;
	cin >> n;
	
	// 赋值
	for(int i=1;i<=n;i++) 
		cin >> stu[i].name >> stu[i].chi >> stu[i].mat >> stu[i].en;
	
	// 求最大值
	int maxn = -1, index = -1;
	for(int i=1;i<=n;i++){
		// 总分
		int total = stu[i].chi + stu[i].mat + stu[i].en;
		if (maxn < total) maxn = total, index = i;
	}
	
	// 输出最厉害
	cout << stu[index].name << " " << stu[index].chi << " " 
		 << stu[index].mat << " " << stu[index].en;
	
	return 0;
}

134. 1953. 新生舞会

主讲老师 - 姚俞坚

1. 代码详解

#include <iostream>
#include <cstring>
using namespace std;

// 结构体
struct info {
	char name[20];
	char uid[10];
	char sex;
};

struct info stu[1010];
int n;

// 性别判断
char getSex(char str[], int mark) {
	char sex;
	for(int j=1;j<=n;j++){
		char tmp[20];
		if (mark == 0) strcpy(tmp, stu[j].uid);
		else strcpy(tmp, stu[j].name);
		// 对比所有uid或name
		if (strcmp(str, tmp) == 0) {
			sex = stu[j].sex;
		}
	}
	return sex;
}

// isD
char isD(char s[]) {
	if (isdigit(s[0])) return getSex(s, 0);
	else return getSex(s, 1);
}


int main() {
	cin >> n;
	
	// 赋值
	for(int i=1;i<=n;i++) 
		cin >> stu[i].name >> stu[i].uid >> stu[i].sex;
	
	// 询问
	int m;
	cin >> m;
	char s1[20], s2[20];
	
	for(int i=1;i<=m;i++){
		// 读入一组询问
		cin >> s1 >> s2;

		// 判断性别
		if (isD(s1) == isD(s2)) cout << "N" << endl;
		else cout << "Y" << endl;
	}
	
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值