作业题笔记-算法

😆
先用python3写,再c++
打*号就是下次自测要测

4-2

notion image
关于步长的问题
数据保证的意义
知道该考虑哪些边界值
这里是0,99.9(虽然其实没多大意义)
简化问题,不必考虑太多特殊输入和异常情况处理,专注于算法本身(其它课可能要考虑实际生产)
notion image
notion image
python没有严格的主函数规定
关于python的if __name__ == "__main__":,并对比和c++主函数的区别

步长问题,循环和累加
对累加数值的变化处理

4-3

notion image
关于数据范围
常见的整数量级边界,较大数处理
c++的int类型是32位,+-2,147,483,647,long long类型为64位,+-9,223,372,036,854,775,807,大到无法想象
python无限精度
notion image
切片操作符的用法
正负数的处理
notion image
字符串库和通用算法库
abs()
reverse()
迭代器
stoi()
int自动忽略前导零

对数字的处理可以转为字符串,是高层次的处理方法(符合我的哲学😉)
整数类型对前导零的自动处理

4-4

这个题目出得太烂了,有眼睛的人都看得出来。遂改。
这个题目出得太烂了,有眼睛的人都看得出来。遂改。
notion image
notion image
notion image
notion image
两种语言对于浮点数的处理有所不同

基本的递归和迭代算法,以及公式方法的代码表达

4-5

notion image
要求输入n是为了静态数组,但是对于现代编程来说有点冗余
notion image
input()返回字符串
split()默认按空格拆分字符串
int() 是个函数
list()将可迭代对象转化为列表
notion image

几个函数的用法,和一些细节

4-6

notion image
提取定义
连续自然数的定义 a[i]=a[i-1]+1
notion image
notion image

对题目的数学拆解,再翻译为编程语言
独立思考算法
需要用到的变量
循环条件的处理

4-7

题目已经限制只有两个质因数
题目已经限制只有两个质因数
数学原理
先找因数,后找质数
从小遍历,找最小的那个,除了,另一个就是最大的
notion image
notion image
/ 在python里总是执行浮点数除法(//可以向下取整),在c++里对整数整数除法,对浮点数浮点数除法

关于质因数的算法

4-8

notion image
以数据变化规律来定义算法
后一个数是value+1
notion image
notion image
setw()setfill()

镶嵌循环
设置格式化字符串输出

4-9

notion image
notion image
notion image
先排序,后去掉最大值和最小值
注意精确到两位小数

一些计算用的函数
格式化方法

4-10

notion image
等差数列
求和公式
notion image
回顾了等差数列

等差数列和求和公式

5-1

notion image
#include <bits/stdc++.h> using namespace std; int main() { int M,N; cin>>M>>N; //vector初始化用(),表示有多少位置 vector<int> count(10,0); for (int i=M;i<=N;i++) { int num=i; while (num>0) { //一位一位来,先取最低位 int digit=num%10; //对应位数加一 count[digit]++; //去掉最低位 num/=10; } //对0单独处理 if(num==0)count[0]++; } for (int i=0;i<10;i++) { cout<<count[i]<<" "; } cout<<endl; return 0; }

数字处理,最低位处理
数字对应数组序列,计数加加

5-2

notion image
#include <bits/stdc++.h> using namespace std; int main() { //题目要求输入n个数,以后不写注释了 int n; cin>>n; //存储n个数,向量定义 vector<int> numbers(n); //set<>只存储不重复的数 set<int> setNumbers; //存储 for (int i=0;i<n;i++) { cin>>numbers[i]; //再.insert插入,会忽略重复的数字 setNumbers.insert(numbers[i]); } //计数,题目要求输出,以后也不写注释了 int count=0; for (int i=0;i<n;i++) { //防止重复查找 for (int j=i+1;j<n;j++) { //.find() 没找到返回.end() if (setNumbers.find(numbers[i]+numbers[j])!=setNumbers.end()) { count++; } } } cout<<count<<endl; return 0; }

复制传入的数
防止重复计数的双重循环

5-3

notion image
#include <bits/stdc++.h> using namespace std; int main() { int n,m; cin>>n>>m; vector<int> pain(n); for (int i=0;i<n;i++) { cin>>pain[i]; } int minPain=INT_MAX; for (int i=0;i<=n-m;i++) { int currentPain=0; for (int j=i;j<i+m;j++) { currentPain+=pain[j]; } if (currentPain<minPain) minPain=currentPain; } cout<<minPain<<endl; return 0; }

窗口问题
循环更新变量current

5-4

notion image
#include <bits/stdc++.h> using namespace std; int main() { int s1, s2, s3; cin >> s1 >> s2 >> s3; //以数组下标表示结果,最大和为三个相加 vector<int> count(s1 + s2 + s3 + 1, 0); for (int i = 1; i <= s1; i++) { for (int j = 1; j <= s2; j++) { for (int k = 1; k <= s3; k++) { //sum既是结果也是下标,最后以下标表示结果,即sum=i(下一个的)=result int sum = i + j + k; count[sum]++; } } } int maxCount = 0; int result = 0; for (int i = 3; i <= s1 + s2 + s3; i++) { //如果很多个结果相同,只输出最小的那个i——即无“=”号的用法 if (count[i] > maxCount) { maxCount = count[i]; result = i; } } cout<<result<<endl; return 0; }

下标可以作为结果 ,vector的值作为频率

5-5

notion image
notion image
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; //无限长路灯 const int max=INT_MAX; vector<bool> lights(max+1,false); //n次操作,每次输入新的数值 for (int i=0;i<n;i++) { double a; int t; cin>>a>>t; for (int j=1;j<=t;j++) { //floor()向下取整 int base=floor(a*j); //翻转则! lights[base]=!lights[base]; } } for (int i=1;i<=max;i++) { if(lights[i]) { cout<<i<<endl; //随时return 0; return 0; } } cout<<-1<<endl; return 0; }

向下取整函数floor()
布尔类型翻转
序列号的标识作用

5-6

notion image
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; //初始化矩阵,先存储,后面格式化输出 vector<vector<int>> matrix(n,vector<int>(n,0)); int num=1; //规定行列,便于移位 int top=0,bottom=n-1,left=0,right=n-1; //while循环,当num<=n*n时,循环继续 while (num<=n*n) { //从左到右 for (int i=left;i<=right;i++) { matrix[top][i]=num++; } //更新top top++; //在右边从上到下 for (int i=top;i<=bottom;i++) { matrix[i][right]=num++; } //更新右侧 right--; //从右往左 for (int i=right;i>=left;i--) { matrix[bottom][i]=num++; } //更新底部 bottom--; //从下到上 for (int i=bottom;i>=top;i--) { matrix[i][left]=num++; } //更新左侧 left++; } //矩阵循环输出 for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { //setw()控制格式化输出,至少占x宽度 cout<<setw(3)<<matrix[i][j]; } cout<<endl; } return 0; }

格式化输出,分解题意,更新变量
矩阵初始化、填充和输出
while()在某些时候特别好用
setw()控制输出宽度

5-7

notion image
#include <bits/stdc++.h> using namespace std; int main() { int n; cin >> n; //二维向量初始化,只知道有几行 vector<vector<int>> triangle(n); //循环设定值,规定行 for (int i=0;i<n;i++) { //resize()调整长度 triangle[i].resize(i+1); //首末为1 triangle[i][0]=triangle[i][i]=1; //中间部分,序列从1开始,到i结束。j<i也有i必须大于1的意思 for (int j=1;j<i;j++) { //数学部分 triangle[i][j]=triangle[i-1][j-1]+triangle[i-1][j]; } } //二维向量循环输出 for (int i=0;i<n;i++) { //j<=i,输出长度控制 for (int j=0;j<=i;j++) { //只是[i][j]而已 cout<<triangle[i][j]; } cout<<endl; } return 0; }

杨辉三角triangle[i][j]=triangle[i-1][j-1]+triangle[i-1][j];
二维向量
二维输出双重循环

5-8

notion image
#include <bits/stdc++.h> using namespace std; //初始化静态矩阵,假设最大为1000 const int MAX_N=1000; //布尔类型 bool illuminated[MAX_N][MAX_N]; //边界检查 bool isValid(int x,int y,int n) { return x>=0&&y>=0&&x<n&&y<n; } //火把 void illuminateTorch(int x,int y,int n) { for (int i=-2;i<3;i++) { if(isValid(x,y+i,n))illuminated[x][y+i]=true; } for (int i=-2;i<3;i++) { if(isValid(x,y+i,n))illuminated[x+i][y]=true; } for (int i=-1;i<2;i++) { for (int j=-1;j<2;j++) { if(isValid(x,y+i,n))illuminated[x+i][x+j]=true; } } } //萤石 void illuminateGrowingStone(int x,int y,int n) { for (int i=-2;i<3;i++) { for (int j=-2;j<3;j++) { if(isValid(x+i,y+i,n))illuminated[x+i][y+j]=true; } } } int main() { int n,m,k; cin>>n>>m>>k; //初始化输入,布尔类型 for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { illuminated[i][j]=false; } } //火把输入 for (int i=0;i<m;i++) { int x=0,y=0; cin>>x>>y; //位置转索引 x--;y--; illuminateTorch(x,y,n); } //萤石 for (int i=0;i<k;i++) { int x=0,y=0; cin>>x>>y; //位置转索引 x--;y--; illuminateGrowingStone(x,y,n); } //计数 int count=0; for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { if(!illuminated[i][j]) { count++; } } } cout<<count<<endl; return 0; }

布尔类型的静态数组&划定边界
边界检查,bool类型
位置转索引

5-9

notion image

*5-10

notion image
#include <bits/stdc++.h> using namespace std; int main() { int n; cin>>n; //目前要输出的是0,之后每次输出完一次就替换为另一个,使用1-current_char int current_char=0; //要输出的数目 int current_to_fill=0; //已经输出的 int filled=0; //while循环,结束条件为已经输出完了n*n个数 while (filled<n*n) { //读取 cin>>current_to_fill; //运行读取的数目这么多次数 for (int i=0;i<current_to_fill;i++) { cout<<current_char; filled++; //换行的条件 if(filled%n==0) { cout<<endl; } } //切换接下来要输出的数 current_char=1-current_char; } return 0; }

while循环的结束条件
__%n==0还可以作为换行的条件
还是先写注释再写实现

5-11

notion image
#include <bits/stdc++.h> using namespace std; //翻转90度 vector<vector<char>> rotate90(const vector<vector<char>>& matrix) { int n=matrix.size(); vector<vector<char>> rotated(n,vector<char>(n)); for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { //矩阵变化 rotated[j][n-1-i]=matrix[i][j]; } } return rotated; } //水平翻转 vector<vector<char>> flipHorizontal(const vector<vector<char>>& matrix) { int n=matrix.size(); vector<vector<char>> flipped(n,vector<char>(n)); for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { flipped[i][n-1-j]=matrix[i][j]; } } return flipped; } //判断是否相等 bool isEqual(const vector<vector<char>>& mat1,const vector<vector<char>>& mat2){ int n=mat1.size(); for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { if(mat1[i][j]!=mat2[i][j])return false; } } return true; } int main() { int n; cin>>n; //变化前和变换后的矩阵 vector<vector<char>> initial(n,vector<char>(n)); vector<vector<char>> target(n,vector<char>(n)); //根据传入的内容初始化。cin自动忽略换行符。换行也结束,char完了也结束 for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { cin>>initial[i][j]; } } for (int i=0;i<n;i++) { for (int j=0;j<n;j++) { cin>>target[i][j]; } } //判断是否相等,并依据题目确定返回值;不能return 1,是表示其它状况。要输出 if(isEqual(target,rotate90(initial))) { cout<<1<<endl; return 0; } if(isEqual(target,rotate90(rotate90(initial)))) { cout<<2<<endl; return 0; } if(isEqual(target,rotate90(rotate90(rotate90(initial))))) { cout<<3<<endl; return 0; } if(isEqual(target,flipHorizontal(initial))) { cout<<4<<endl; return 0; } if (isEqual(target,rotate90(flipHorizontal(initial)))) { cout<<5<<endl; return 0; } if (isEqual(target,rotate90(rotate90(flipHorizontal(initial))))) { cout<<5<<endl; return 0; } if (isEqual(target,rotate90(rotate90(rotate90(flipHorizontal(initial)))))) { cout<<5<<endl; return 0; } if (isEqual(target,initial)) { cout<<6<<endl; return 0; } cout<<7<<endl; return 0; }

矩阵翻转、水平翻转
 
 

6-1

notion image
字典
notion image

字典,一一对应
getline()

6-2

notion image
notion image
对题目的分析
只能改一个字符,那么1.vv改为vk 2.kk改为vk
不能破坏原有的vk
列出特殊情况 vvk、vkk(修改vv时,如果是vvk,那么会变,修改kk时,如果是vkk,那么会变)
notion image

对题目的分析

6-3

notion image
题目解析
找到就跳过
先处理多的,再处理少的
我做的是这样
#include<iostream> #include <string> using namespace std; pair<int,int> cout_boy_and_girl(const string&s) { int boy_count=0; int girl_count=0; for (int i=0;i<s.length();i++) { if(i+2<s.length()&&s[i]=='b'&&s[i+1]=='o'&&s[i+2]=='y') { boy_count++; i+=2; }if(i+1<s.length()&&s[i]=='b'&&s[i+1]=='o') { boy_count++; i++; }if(i+1<s.length()&&s[i]=='o'&&s[i+1]=='y') { boy_count++; i++; }if(s[i]=='b') { boy_count++; }if(s[i]=='o') { boy_count++; }if(s[i]=='y') { boy_count++; }if(i+3<s.length()&&s[i]=='g'&&s[i+1]=='i'&&s[i+2]=='r'&&s[i+3]=='l') { girl_count++; i+=3; }if(i+2<s.length()&&s[i]=='g'&&s[i+1]=='i'&&s[i+2]=='r') { girl_count++; i+=2; }if(i+2<s.length()&&s[i]=='i'&&s[i+1]=='r'&&s[i+2]=='l') { girl_count++; i+=2; }if(i+1<s.length()&&s[i]=='g'&&s[i+1]=='i') { girl_count++; i++; }if(i+1<s.length()&&s[i]=='r'&&s[i+1]=='l') { girl_count++; i++; }if(i+1<s.length()&&s[i]=='i'&&s[i+1]=='r') { girl_count++; i++; }if (s[i]=='g') { girl_count++; }if (s[i]=='i') { girl_count++; }if (s[i]=='r') { girl_count++; }if (s[i]=='l') { girl_count++; } } return make_pair(boy_count,girl_count); } int main(){ string s; cin>>s; cout<<cout_boy_and_girl(s).first<<endl<<cout_boy_and_girl(s).second<<endl; return 0; }
但这样是对的
#include <bits/stdc++.h> using namespace std; pair<int,int> count_boy_and_girl(const string&s) { int count_boy=0; int count_girl=0; for (int i=0;i<s.length();i++) { if(i+2<s.length()&&s[i]=='b'||s[i+1]=='o'||s[i+2]=='y') count_boy++; if(i+3<s.length()&&s[i]=='g'||s[i+1]=='i'||s[i+2]=='r'||s[i+3]=='l') count_girl++; } return make_pair(count_boy,count_girl); } int main() { string s; cin>>s; cout<<count_boy_and_girl(s).first<<endl<<count_boy_and_girl(s).second<<endl; return 0; }
说实话有点理解不了。我知道我有错,但是我理解不了答案🤣
GPT也难以理解,那就算了。

#include<bits/stdc++.h>
字符串处理
pair<>,make_pair(),.first,.second

6-4

notion image
notion image
转化为字符串
reverse()
s.find() 、size_t、s.substr()
s.pop_back()
string::npos s.find()未找到的返回值

数字处理转化为字符串处理

6-5

notion image
直接简化题目开做
#include <bits/stdc++.h> using namespace std; int main() { //map,直接平方,对应题目要求 map<string,int> word_to_square={ {"zero", 0}, {"one", 1}, {"two", 4}, {"three", 9}, {"four", 16}, {"five", 25}, {"six", 36}, {"seven", 49}, {"eight", 64}, {"nine", 81}, {"ten", 0}, {"eleven", 21}, {"twelve", 44}, {"thirteen", 69}, {"fourteen", 96}, {"fifteen", 25}, {"sixteen", 56}, {"seventeen", 89}, {"eighteen", 24}, {"nineteen", 61}, {"twenty", 0}, {"a", 1}, {"both", 4}, {"another", 1}, {"first", 1}, {"second", 4}, {"third", 9} }; vector<int> squares; string s; //有满足要求的输入就push_back() for (int i=0;i<6;i++) { cin>>s; if(word_to_square.find(s)!=word_to_square.end()) squares.push_back(word_to_square[s]); } //排序 sort(squares.begin(),squares.end()); //标志位 bool first_output=true; //遍历number,按条件输出 for (int number: squares) { //第一个输出,不要前导零 if(first_output&&number!=0) { cout<<number; first_output=false; } //其余输出,格式化printf(“%_",_) else { //测试不过,但是加了if就改好了 //想想为什么这样改是对的,因为……程序运行是这样的 if(number!=0) { printf("%.2d",number); } } } //如果没有第一个输出,也就是没有符合条件的值,输出0,即题目要求的 if(first_output)cout<<0<<endl; return 0; }
notion image
但是出了问题就改,代码不是很容易变成”屎山“吗
哈哈,你提到的“屎山”问题,确实是许多程序员都会遇到的困境。所谓“屎山”代码,指的是代码结构混乱、难以维护、难以扩展的问题。虽然我们强调“先跑通,再优化”的方法,但是如果没有好的规划和设计,确实可能会导致代码变得臃肿混乱,让后续的维护和扩展变得非常困难。
不过,防止代码变成“屎山”其实也是有办法的!我们可以通过一些良好的编程习惯和设计思路,保持代码的清晰和可维护性。接下来,我给你几个小建议,帮助你在“先做出来”的过程中,逐步提升代码质量,避免堆成“屎山”。

1. 适时重构,避免“越改越乱”

你在解决问题的时候,刚开始不必追求完美,先跑通程序,这个没问题。但一旦你发现代码跑通了,接下来就该考虑重构了。重构的意思是,在保持功能不变的前提下,对代码进行结构调整,让它更清晰、易读和易于维护。
  • 什么时候重构? 当你发现代码开始变得难以理解、逻辑重复、功能散乱时,就是重构的信号。不要等代码已经成了“屎山”才动手,早点维护更好。
  • 怎么重构? 你可以逐步把重复的逻辑抽取成函数,把复杂的条件分支简化,把耦合度高的部分拆分成独立模块。通过重构,代码会变得更有结构和条理。

2. 遵循单一职责原则

在编程中,每一块代码应当只负责一件事。如果一个函数或者一个模块承担了太多职责,它就容易变得复杂和难以维护。例如,一个函数既要处理文件读取,又要处理数据逻辑,还要负责错误处理,这样的代码很容易变成“屎山”。
解决办法是,拆分功能模块,让每个函数或类只做它该做的事。这样既方便以后修改,也更容易进行单元测试。

3. 保持代码简洁,少用硬编码

很多“屎山”代码的特点是充满了“硬编码”,也就是直接在代码中写死各种数字、字符串等参数。如果这些参数一旦变化,你就需要到处修改代码,极易出错。
解决办法是:把这些“硬编码”的值变成常量,或者放到配置文件中统一管理。这样不仅减少了代码中的混乱,也让后续的修改变得简单。

4. 及时写注释和文档

“屎山”代码另一个大问题就是:写了代码,过了一段时间连自己都看不懂了。所以,适当的注释和文档非常重要,特别是在逻辑复杂的地方。好的注释不需要过多,但应该能够解释为什么要这么做,而不是做了什么。代码文档可以帮助你回忆起当时的思路,也方便别人(或者未来的自己)来维护代码。

5. 进行单元测试,确保代码的可维护性

单元测试不仅能保证你写的代码是正确的,还能让你有信心在不怕“破坏”其他功能的前提下,进行重构和优化。测试代码能帮助你捕捉到“屎山”生成的苗头,让你及时止损,避免代码质量的进一步恶化。

6. 使用版本控制,保持代码的清晰性

如果你在项目中使用了版本控制(如 Git),每次你修改代码时都可以记录修改内容和原因。这样你不仅可以追溯之前的版本,还可以有条理地管理你的代码变化。尤其当你在重构代码时,版本控制能帮你避免因为不小心修改导致的崩溃。

总结一下:

你先跑通程序再逐步改进的思路是非常好的,但为了避免“屎山”问题,适时重构和保持代码的清晰性是非常重要的。初期代码跑通后,一定要有意识地整理、重构,把复杂、冗长的部分进行优化,遵循“单一职责”和“少硬编码”的原则。这样,你既能享受快速迭代的乐趣,又能确保代码的质量和可维护性。
总之,写代码就像盖房子:先把地基打好,结构搭出来,然后一边使用,一边慢慢装修和维护。最终,你会得到一座结构坚固、装潢漂亮的房子,而不是一堆乱七八糟的建筑材料。
知识就是关于可能性和偶然性的吗
你问的这个问题其实触及了哲学中的知识论(epistemology),也涉及到概率、确定性、以及知识的本质等多个深刻的议题。简单回答来说,知识不仅仅是关于可能性和偶然性,但这些概念确实在讨论知识时发挥了重要作用。为了让这个问题更加清晰易懂,我们从几个角度来逐步展开这个问题。

1. 知识的传统定义:真、信念、理由

古希腊哲学家柏拉图曾给出过一个经典的知识定义,即“知识是经过良好论证的真信念”。这个定义后来演变为三要素:
  • 信念:你首先得相信某件事是真的。比如,你相信明天会下雨。
  • :这件事得确实是真的。比如,明天真的下雨了。
  • 理由(或证据):你得有合理的理由或者证据来支持你为什么这么相信。比如,你看了天气预报,知道明天有80%的可能性会下雨。
在这个定义下,知识不仅仅是对事实的猜测,还需要你有合理的依据来支撑你的信念。如果你没有理由,只是碰巧猜对了,虽然结果对了,但这还不算是“真正的知识”,而是偶然的运气。

2. 可能性与偶然性在知识中的地位

那“可能性”和“偶然性”在知识中起什么作用呢?这要看我们怎么理解“确定性”。
  • 可能性:在很多实际情况中,我们的知识并非是100%确定的,而是基于概率可能性。比如,气象学家不能100%确定明天会不会下雨,但可以说“有80%的可能性”。这样的知识就是基于对可能性的分析。
  • 偶然性:偶然性则涉及到我们如何解释突发的、不确定的事件。有时,事情发生并不是因为我们完全理解或掌握了它的规律,而只是由于偶然的因素。比如,你随机猜测某支股票明天会上涨,结果涨了,这算是一种偶然成功,不能称为知识,因为你没有掌握足够的市场信息和分析手段。
总结来说,可能性和偶然性更多地影响了我们如何获取和评估知识,但它们本身并不是知识的全部。

3. 科学中的可能性:知识与不确定性

在科学领域,知识往往是与可能性和不确定性密切相关的。例如,在量子力学中,粒子的状态就是以概率分布形式存在的,我们只能确定某种可能性,而不是绝对的确定性。
  • 科学知识往往依赖于实验、观测和理论的验证。在这种知识体系中,很多结论是基于当前的证据和推测,但并不能完全排除偶然性或误差。例如,科学理论中的预测常常有一定的误差范围,这就是在处理知识时,可能性和偶然性介入的一个例子。

4. 知识、偶然性和概率的例子:Gettier问题

哲学家埃德蒙·葛梯尔(Edmund Gettier)提出过一个著名的问题,挑战了“真信念+理由=知识”的传统定义。葛梯尔问题展示了即便我们有真信念和理由,偶然性依然可能让我们产生错误的知识。
举个简单的例子:你站在一个草地上,看到远处有一头牛,于是你相信“草地上有一头牛”。事实上,你看到的只是一个模型,而草地上确实有一头牛躲在一棵树后。虽然你相信的结论是正确的,但这更像是偶然的结果,而不是基于你正确的观察和理解。因此,你的知识是不可靠的。
这个例子表明,偶然性有时会让我们误以为我们掌握了知识,但实际上我们的信念可能是靠运气得来的,而不是可靠的知识。

5. 综合:知识的多维度

综上所述,知识不仅仅是关于可能性和偶然性,但这两者确实在我们获得和评价知识时起到了重要作用。完整的知识应该包含:
  • 真实的信念:对事物的真实认知。
  • 合理的理由或证据:我们需要有依据来相信我们的结论。
  • 对可能性和偶然性的考量:在不确定的情况下,我们往往需要依赖概率和可能性来做判断。
因此,在实际操作中,知识是确定性与不确定性的结合,我们可以通过概率论、统计学和逻辑推理来处理这些不确定性,但这不代表知识本质上仅仅是偶然性和可能性。

总结

知识确实包含了可能性和偶然性这两个因素,但它们并不是知识的全部。完整的知识需要信念、真相和合理的依据,而偶然性和可能性更多地影响我们如何获取、评估和确认这些知识。知识是一种对于世界的理性认识,偶然性和可能性则是其中不可避免的一部分
notion image

map
sort
特殊情况特殊处理

6-6

notion image
#include <bits/stdc++.h> using namespace std; //按题目要求处理字符串 int computeMod47(string s) { //作为乘的基数 int result=1; //遍历单个字符处理 for (char ch: s) { //ch-‘A'=0 result*=ch-'A'+1; result%=47; } return result; } int main() { string cometName,groupName; cin>>cometName>>groupName; int cometResult=computeMod47(cometName); int groupResult=computeMod47(groupName); if(cometResult==groupResult) cout<<'GO'<<endl; else cout<<'STAY'<<endl; return 0; }

字符串转数字处理
遍历单个字符
乘的基数 result=1;return result;

6-7

notion image
#include <bits/stdc++.h> using namespace std; int main() { int a=0,b=0,c=0; string input; getline(cin,input); //标志位 size_t pos=0; //以=号分割 while ((pos=input.find('='))!=string::npos) { //剪裁 .substr() string statement=input.substr(0,pos+2); //找到了之后删掉,再处理,已经存了 input.erase(0,pos +3); char variable=statement[0]; char value=statement[3]; if(value>='0'&&value<='9') { //字符转数字 _-'0' int numValue=value-'0'; if(variable=='a') a=numValue; if (variable=='b') b=numValue; if(variable=='c') c=numValue; }else { if (variable=='a') a=(value=='a')?a:(value=='b')?b:c; if (variable=='b') b=(value=='a')?a:(value=='b')?b:c; if (variable=='c') c=(value=='a')?a:(value=='b')?b:c; } } cout<<a<<" "<<b<<" "<<c<<endl; return 0; }

字符串处理
.substr()
.erase()
size_t pos=s.find(’_’),返回序列,找不到返回string::npos

6-8

notion image
#include <bits/stdc++.h> using namespace std; int main() { //存储字符出现的频率 vector<int>freq(26,0); //读取line string line; //读取四行 for (int i=0;i<4;i++) { //getline(cin, line) getline(cin,line); //处理单个字符 for (char ch: line) { //ch-'A' freq[ch-'A'] if(ch>='A'&&ch<='Z') { freq[ch-'A']++; } } } //从最大频率开始,从高到低,从左到右输出 //初始化最高频率 int maxFreq=0; //遍历freq for (int count: freq) { if(count>maxFreq) maxFreq=count; } //从高到低即倒序 for (int i=maxFreq;i>0;--i) { //从左到右即正序 for (int j=0;j<26;j++) { //如果遍历到的字母的频率大于等于目前行的频率 if(freq[j]>=i) { cout<<'*'; }else { cout<<' '; } //对字母隔开有空格 if(j<25) { cout<<' '; } } //换行 cout<<endl; } //末行输出 for (int i=0;i<26;i++) { //第一个字母前没有空格 if(i>0) cout<<' '; //char()转换数字为字符 cout<<char('A'+i); } cout<<endl; return 0; }

输出格式排版
字符转数字转字符

7-3

notion image
#include <bits/stdc++.h> using namespace std; bool isPrime(int n) { if(n<2)return false; for (int i=2;i<sqrt(n)+1;i++) { if (n%i==0)return false; } return true; } int main() { int n; cin>>n; for (int i=1;i<sqrt(n)+1;i++) { //找小的因数 if (n%i==0) { //判断是否为质数,通过小的质数输出大的质数 if (isPrime(i)) { cout<<n/i<<endl; break; } } } return 0; }

找质因数

7-4

notion image
#include <bits/stdc++.h> using namespace std; //判断是否是质数 bool isPrime(int n) { if(n<2)return false; for (int i=2;i<sqrt(n)+1;i++) { if (n%i==0)return false; } return true; } int main() { int n; cin>>n; for (int i=5;i<=n;i++) { //标志位 bool isFound=false; //偶数 if (i%2==0) { //找小的被加数,j<i/2+1 for (int j=2;j<i/2+1;j++) { //判断是否为质数 if (isPrime(j)&&isPrime(i-j)) { cout<<i<<"="<<j<<"+"<<i-j<<endl; isFound=true; //找到一对就退出内循环 break; } } if (!isFound) { cout << i << "No qualifying numbers " << endl; } } } return 0; }

标志位的适用场景:找到符合条件的就退出(配合使用break),利用标志位处理后续操作
质数相加对循环条件相对于质数相乘的区别

7-5

notion image
#include <bits/stdc++.h> using namespace std; //判断是否是质数 bool isPrime(int n) { if(n<2)return false; for (int i=2;i<sqrt(n)+1;i++) { if (n%i==0)return false; } return true; } //判断是否是回文数 bool isPalindrome(int n) { //转化为string,使用reverse函数 string s=to_string(n); string rev_s=s; reverse(rev_s.begin(),rev_s.end()); //return比较的结果 return rev_s==s; } int main() { int a,b; cin>>a>>b; for (int i=a;i<=b;i++) { if (isPrime(i)&&isPalindrome(i)) { cout<<i<<endl; } } return 0; }

回文数,转化为字符串处理

7-6

notion image
#include <bits/stdc++.h> using namespace std; int main() { //传入s,istream_iterator为标准库函数,自动读取所有符合条件的内容,直到输入流结束 vector<int> s((istream_iterator<int>(cin)),istream_iterator<int>()); long long totalSum=0; //每个元素在所有子集中出现的次数,都是一样的,组合数学知识。把1左移n-1位,就是2^(n-1) long long muliplier=1LL<<(s.size()-1); //求所有子集的和 for (int i=0;i<s.size();i++) { //累加元素*元素出现的次数 totalSum+=s[i]*muliplier; } cout<<totalSum<<endl; return 0; }

组合数学,所有子集里每个元素出现的总次数是2^(n-1)
istream_iterator<>()库函数,自动读取所有符合条件的数,直到输入流结束

7-8

notion image
#include <bits/stdc++.h> using namespace std; int main() { //输入n int n=0; cin>>n; //过程模拟 int peaches=1; //从n天倒推 for (int i=n;i>1;i--) { peaches=(peaches+1)*2; } cout<<peaches<<endl; return 0; }

简单

7-9

notion image
#include <bits/stdc++.h> using namespace std; //结构体初始化 struct Student { string name; int age; int noipScore; }; int main() { //读取学员人数 int n; cin>>n; //初始化 vector<Student> students(n); for (int i=0;i<n;i++) { cin>>students[i].name>>students[i].age>>students[i].noipScore; } //计算 for (int i=0;i<n;i++) { if(students[i].noipScore<600) { students[i].noipScore=static_cast<int>(students[i].noipScore*1.2); if(students[i].noipScore>600) { students[i].noipScore=600; } } if(students[i].age) { students[i].age++; } } //输出 for (int i=0;i<n;i++) { cout<<students[i].name<<" "<<students[i].age<<" "<<students[i].noipScore<<endl; } return 0; }

结构体初始化和简单使用
static_cast<>()类型转换

例4-3

notion image
#include <bits/stdc++.h> using namespace std; int main() { int n,k; cin>>n>>k; //注意用double double sumA=0,sumB=0; int countA=0,countB=0; for (int i=1;i<=n;i++) { if(i%k==0) { //累加i sumA+=i; countA++; } else { sumB+=i; countB++; } } //隐式转换 double avgA=sumA/countA; double avgB=sumB/countB; //fixed、setprecision() cout<<fixed<<setprecision(1)<<avgA<<" "<<avgB<<endl; return 0; }

简单

例4-4

notion image
#include <bits/stdc++.h> using namespace std; int main() { int a; cin>>a; int lenth=a; int count=1; while (lenth!=1) { lenth/=2; count++; } cout<<count; return 0; }

简单

例4-6

notion image
#include <bits/stdc++.h> using namespace std; int main() { int n; cin>>n; int num=1; //利用n递减作为numPerRow for (int i=n;i>0;i--) { for (int j=1;j<=i;j++) { cout<<setw(2)<<setfill('0')<<num; num++; } cout<<endl; } return 0; }

i递减的意义还能利用i

例4-7

notion image
#include <bits/stdc++.h> using namespace std; int main() { int n; cin>>n; long long sum=0; long long factorial=1; for (int i=1;i<=n;i++) { //factorial每次循环再更新,继承前一次的 factorial*=i; sum+=factorial; } cout<<sum<<endl; return 0; }

特定阶乘的妙用,变量继承自上一次的结果,循环的妙用

例4-8

notion image
#include <bits/stdc++.h> using namespace std; int main() { int n,x; cin>>n>>x; int count=0; //转化为字符 char target='0'+x; for (int i=1;i<=n;i++) { //转化为字符串 string s=to_string(i); //对单个字符比较 for(char c:s) { if (c==target) { count++; } } } cout<<count<<endl; return 0; }

数字转为字符和字符串处理

例4-9

notion image
#include <bits/stdc++.h> using namespace std; int main() { int k; cin>>k; float sum=0; int n=0; while (sum<=k) { //while里加计数器 n++; sum+=1.0/n; } cout<<n<<endl; return 0; }

while循环里加计算器

例4-10

notion image
#include <bits/stdc++.h> using namespace std; int main() { int k; cin>>k; long long sum=0; int level=1; int day=1; while (day<=k) { for (int i=0;i<level;i++) { //防止在for循环内day超过k if(day>k)break; day++; sum+=level; } level++; } cout<<sum<<endl; return 0; }

while加for循环的注意事项

例4-11

notion image
#include <bits/stdc++.h> using namespace std; int main() { int n; cin>>n; long sum=0; for (int i=1;i<=n;i++) { sum+=i; } cout<<sum<<endl; return 0; }

简单

例4-13

notion image
#include <bits/stdc++.h> using namespace std; bool isPrime(int n){ if (n<2)return false; //对2、3单独处理 if(n<4)return true; for (int i=2;i<sqrt(n)+1;i++) { if (n%i==0)return false; } return true; } int main() { int l; cin>>l; long long sum=0; int i=0; int count=0; while (sum<=l) { i++; if (isPrime(i)) { sum+=i; //如果加了之后大于目标数,那就别加count和输出i了。要的只是count和i if (sum>l)break; count++; cout<<i<<endl; } } cout<<count<<endl; return 0; }

判断质数函数的优化
根据输出结果修改答案

例4-14

notion image
#include <bits/stdc++.h> using namespace std; bool isPrime(int n){ if (n<2)return false; //对2、3单独处理 if(n<4)return true; for (int i=2;i<sqrt(n)+1;i++) { if (n%i==0)return false; } return true; } bool isPalindrome(int n) { string s=to_string(n); //reverse()不返回值,而是修改值 string reversed_s=s; reverse(reversed_s.begin(),reversed_s.end()); if (s==reversed_s)return true; return false; } int main() { int a,b; cin>>a>>b; for (int i=a;i<=b;i++) { if (isPrime(i)&&isPalindrome(i))cout<<i<<endl; } return 0; }

reverse()修改值而不是返回值

例5-1

notion image
#include <bits/stdc++.h> using namespace std; int main() { int n; cin>>n; vector<int> cute_values(n); for (int i=0;i<n;i++) { cin>>cute_values[i]; } for (int i=0;i<n;i++) { int count=0; for (int j=0;j<i;j++) { if (cute_values[j]<cute_values[i])count++; } cout<<count<<" "; } return 0; }

简单

1427

notion image
#include <bits/stdc++.h> using namespace std; int main() { vector<int> numbers; int num; //能输入,再判定输入是否符合条件 while (cin>>num&&num!=0) { //使用push_back() numbers.push_back(num); } //__.size()获取向量长度大小 for (int i=numbers.size()-1;i>=0;i--) { cout<<numbers[i]<<" "; } cout<<endl; return 0; }

向量的push_back(), size()

5727

notion image
#include <bits/stdc++.h> using namespace std; int main() { int n; cin>>n; //向量,之后方便输出 vector<int> sequence; while (n!=1) { //push_back() sequence.push_back(n); if (n%2==0) { n/=2; }else { n=n*3+1; } } sequence.push_back(1); //倒着输出向量 for (int i=sequence.size()-1;i>=0;i--) { cout<<sequence[i]<<" "; } cout<<endl; return 0; }

对于向量的一般用法,以及.push_back()
💡
有时候思路还是很重要的
notion image
🙂
我又回来了。只要题目难度适中,不在乎在哪里刷!

8-1

notion image

8-2

notion image
notion image

8-3

notion image
notion image

8-4

notion image

8-6

notion image
notion image
notion image

8-7

notion image

8-8

notion image

8-9

notion image

8-10

notion image

9-1

notion image
 

9-2

notion image

9-3

notion image

9-4

notion image

9-5

notion image

9-6

notion image

9-7

notion image