Ctrl + 鼠标左键单击题目即可跳转到官方网站做题

人类最大的敌人是傲慢,其次是无知

前言

本来自己只是再学C++PrimerPlus的过程中找点简单题目保持手感和熟练度的,所以找到了这个网站.

http://ybt.ssoier.cn:8088/index.php

说实话我对自己的猪脑袋还有是自知之明的,自然不会去管那些自己不会的题目.但是有些简单题目还是挺适合现在的我的.而且我在搜寻题解的时候找到了别人自己一个人做的题解汇总

信息学奥赛一本通题解

所以就想着自己反正也做了,就也写一个题解,当做监督自己不要半途而废的外在作用力.这就是我这篇博客的由来.

别人做这个专门拿出来做一份题解

我前面做过的就不做笔记了.,没啥时间而且就算有长进,性价低也不高,我直接从这里开始好好的批判自己的错误就算是狠狠进步了.

这些题解发到博客上还有一个好处,就是不用在本地弄好条理清楚的文件夹,直接把重点题目发到博客上面来算是删繁就简.

基本上只记录自己的错题和一些对自己有训练意义的题目,太简单的题目就没有了.

基础(一) C++语言

1003:对齐输出

*C语言printf(“”)左对齐和右对齐*

https://blog.csdn.net/abcdu1/article/details/74926375

https://blog.csdn.net/Spy_in/article/details/124214390

在 printf 中,无论是 float 类型还是 double 类型,输出都需要用 %f ,在有些系统中用 %lf 也不会出错,但是尽量还是按照标准来

img

这时候输出arr字符数组的大小,也就是整个数组所占的字节数目, 这个时候是包含null字符’\0’的,因此结果是2

2069:【例2.12 】糖果游戏

img

个人错误

没有一开始看出来这是一个简单的模拟,同时总是==想偷懒,不用newa和a来分别表示当下的a和新的a.==

一般都是两个步骤

  1. newa等于a,b,c等等的一个代数表达式
  2. a等于newa,newb,newc等等的一个代数表达式

个人修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;

int main(void)
{
int a, b, c, d, e;
cin >> a;
cin >> b;
cin >> c;
cin >> d;
cin >> e;
int newa = a / 3;

int newb = (newa + b) / 3;
int newc = (newb + c) / 3;
int newd = (newc + d) / 3;
int newe = (newd + e + newa) / 3;
a = newa + newb + newe;
b = newb + newc;
c = newc + newd;
d = newd + newe;
e = newe;
// printf("%d", a);
printf("%5d%5d%5d%5d%5d", a, b, c, d, e);

return 0;
}

2059:【例3.11】买笔

个人错误

买笔题解参考

2059:【例3.11】买笔

个人修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

#include <iostream>
using namespace std;

int main(void)
{
int x;
cin >> x;
int res = x / 4;
int a = 0, b = 0, c; // for 6 5 4
int remainder = x % 4;
switch (remainder)
{
case 0:
c = res;
break;
case 1:
{
b++;
c = res - 1;
}
break;
case 2:
{
a++;
c = res - 1;
}
break;
case 3:
{
b++;
a++;
c = res - 2;
}
break;
default:

break;
}
cout << a << " " << b << " " << c << endl;
return 0;
}

1052:计算邮资

个人错误

个人犯的错误:对于整除的性质理解不够,见到题干

超过1000克的部分,每500克加收超重费4元,不足500克部分按500克计算

就直接写

1
2
3
4
if (x <= 1000)
money = 8;
else
money = 8 + ((x - 1000) / 500 + 1) * 4;

殊不知整除的性质就是 ==如果刚好整除就整除,否则向下取整==

那么对于题干的描述

不足500克部分按500克计算

就要分足500g的时候和不足500g的时候,足500g的时候不用加1;不足500g的时候还是要加1;

个人修改

按照我的思路继续修改代码的应该是这样的.

1
2
3
4
5
6
7
8
9
10
if (x <= 1000)
money = 8;
else
{
int res = (x - 1000) % 500;
if (res)
money = 8 + ((x - 1000) / 500 + 1) * 4;
else
money = 8 + (x - 1000) / 500 * 4;
}

实测通过了

image-20241103175758653

但这样显然还是不够好,从别人的写法中这样写更好.使用ceil函数( 在cmath里面)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <cmath>
using namespace std;

int main(void)
{
int x;
char ch;
int money = 0;
cin >> x;
cin >> ch;
if (x <= 1000)
money = 8;
else
{
money = 8 + ceil((x - 1000) / 500.0) * 4;
}
if ('y' == ch)
money += 5;

printf("%d", money);

return 0;
}

实测也通过了

image-20241103182151940

下面的新的笔记都是在ubuntu里面写的,记得千万不要插入图片,插入图片没设置上传到云服务的,,记录一下核心,锻炼一下语言表达能力.

今天提交次数用完了,等明天吧.

1071:菲波那契数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
using namespace std;
const int N = 80;
int main(void)
{
long long fa[N];
fa[0] = fa[1] = 1;
int k;
cin >> k;
int resIndex = k - 1;
long long a = fa[0], b = fa[1];
while (resIndex--)
{
long long tmp = b;
b = a + b;
a = tmp;
}
cout << a;
return 0;
}

个人修改

这个斐波那契数的循环写法

我写的时候的疑问是

我记得都是return a,一般斐波那契数都是从0开始,因此要为这个题目做一个转换

第k个数对应 的下标(在下标从零开始的时候)Index = k - 1;

这个时候你就没必要管Index具体的值是多少,你就认为Index是你要求的数的下标

再去用

1
2
3
4
5
6
7
while (resIndex--)
{
long long tmp = b;
b = a + b;
a = tmp;
}
cout << a;

你会发现Index等于0, 1, 2, 3, …..时候,你返回到a就是对应斐波那契数列(下标从零开始)的下标为index的数的数值

1112:最大值和最小值的差

错误写法(仍未找到错误原因)

不知道为什么我的写法测试点4总是过不了,有空再看,先标记一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

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

int main(void)
{
int n;
cin >> n;
int q[n];
int min = 20000;
int max = -20000;
for (int i = 0; i < n; i++)
{
cin >> q[i];
if (q[i] < min)
min = q[i];
if (q[i] > max)
max = q[i];
}
cout << max - min;

return 0;
}

google出来的正确写法

1112:最大值和最小值的差-信息学奥赛一本通

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <bits/stdc++.h>

using namespace std;



int main(){



int n,max,min;

cin>>n;

for(int i=0;i<n;i++){

int t;

cin>>t;

if(i==0){

min=t;

max=t;

}

else{

if(t<min){

min=t;

}

if(t>max){

max=t;

}

}

}

cout<<max-min;

return 0;


1116:最长平台

不知为何,自己写这个题目的时候突然感觉自己的脑袋很清晰,觉得每一步都毫无疑问,没有一开始我对这种题目的混沌感.

可能这就是教学相长也,通过讲述帮助自己更加地理清思路的方法.

个人题解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

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

int main(void)
{
int n;
cin >> n;
int q[n];

for (int i = 0; i < n; i++)
{
cin >> q[i];
}
// i定位新的数字,,j定位这个数字的最后一个出现的下标
int i = 0;
int length = 0;
while (i < n)
{
int j = i;
while (j < n && q[j] == q[i])
j++;
// while循环结束时,j == n或者j指向第一个和q[i]不相同的数字
if (j - i > length)
length = j - i;
i = j;//i指向新的数值
}
cout << length;
return 0;
}

1117:整数去重

不知为何,自己写这个题目的时候突然感觉自己的脑袋很清晰,觉得每一步都毫无疑问,没有一开始我对这种题目的混沌感.

可能这就是教学相长也,通过讲述帮助自己更加地理清思路的方法.

思路1

我有两种想法,第一种时开times数组,记录q里面每个数字出现的频次

切到Ubuntu的Clion下面我要debug找一下问题

果然在Clion下面好一些,直接给下面的max + 1标了下划波浪线,说是

Variable-sized object may not be initialized

说这个数组可能没有被数初始化

1
2
int times[max + 1] = {0}; // times数组,记录q里面每个数字出现的频次,没出现过就是零次

但是我后来发现原因不在这,

个人错误1

1
2
3
4
5
6
7
8
9
10
11
12
int res[n]; // res数组存放去重后的结果
// 将times数组里面大于等于一的元素对应的下标,就是q数组的元素
int k = 0; // k是res数组的小标
int i = 0; // i时times数组的下标
while (i < max + 1) {
if (times[i] >= 1) {
res[k] = i;
k++;
i++;
} else
i++;//这里前往别写成i++和k++
}

写成了

1
2
3
4
5
6
7
8
9
10
int res[n]; // res数组存放去重后的结果
// 将times数组里面大于等于一的元素对应的下标,就是q数组的元素
int k = 0; // k是res数组的小标
int i = 0; // i时times数组的下标
while (i < max + 1) {
if (times[i] >= 1)
res[k] = i;
k++;
i++;//这里前往别写成i++和k++
}

后者错误的原因在于,只有满足拷贝 条件的时候,才把i赋值给res[k],同时k向后移动一位,i也向后移动一位

当不满足拷贝条件的时候,i就不赋值给res[k],同时k不用移动,只有i要往后移动一位.

因此这里是有两个要注意的问题

错误点一

是千万不要为了图快而省略if 判断后面花括号,每一個花括号都是咋提醒你这里真的又有一条语句吗???会不会还有一条语句?

尤其是两个指针i 和 j加上while循环里面的if语句,一定一定要加上花括号,来保证你想清楚i++和j ++哪一个在if的花括号里面,哪一个在外面.

错误点二

千万千万别省略每一個花括号,不论是if的还是while的还是for的

你明明可以通过打一个花括号来减少自己思考的范围,你却非要给自己家难度,让自己一头雾水.

同理,不管别人怎么写,我就要每次有一个if我都要写else哪怕写成这样我也要保证就够完整

1
2
3
4
if (true) 
//do something
else
;

甚至就像老师教的那样,我只是知道这里应有一个if语句,但是test进入if语句的条件我还想不清楚,同时//do something我也还没有想清楚,但这都不重要

z最最重要的是你先给我写下面这段代码,,之后再往里面填入.这才是最最重要的.写代码的时候永远先注意整体框架,把简单同时一定能得分的做了.

之后再去考虑细节这些很难同时很可能一点分都拿不到 的内容.

做好最坏打算,最好提高自己下限的事情.

1
2
3
4
5
6
if (true) {
//do something
}
else {

}

这就是结构化编程

的意义,不然为什么艾兹赫尔·戴克斯特拉(Dijkstra)在1968年也提出著名的论文《GOTO陈述有害论》(Go To Statement Considered Harmful)[2],因此结构化编程开始盛行

错误点三

遇到数组拷贝或者两个指针i 和 j 或者遇到while循环这种要自己去思考i ++ 和j ++ 细节的循环,都要给我注意指针的增减,这里指针的增减一定是灵活且复杂的.

同时千万绝对不能写成res[i++] 的写法,虽然我这是什么意思.但是自己写的时候,最好把自己当作傻子来对待,只有把一个高深的内容教会一个傻子你才算学会这个内容.也就是说

只能写成这样

1
2
3
4
5
6
7
8
9
10
11
12
int res[n]; // res数组存放去重后的结果
// 将times数组里面大于等于一的元素对应的下标,就是q数组的元素
int k = 0; // k是res数组的小标
int i = 0; // i时times数组的下标
while (i < max + 1) {
if (times[i] >= 1) {
res[k] = i;
k++;
i++;
} else
i++;//这里前往别写成i++和k++
}

不准给我写成这样,哪怕下面这种写法也是对的.

1
2
3
4
5
6
7
8
9
int res[n]; // res数组存放去重后的结果
// 将times数组里面大于等于一的元素对应的下标,就是q数组的元素
int k = 0; // k是res数组的小标
int i = 0; // i时times数组的下标
while (i < max + 1) {
if (times[i] >= 1)
res[k++] = i;
i++;//这里前往别写成i++和k++
}

个人错误2

下面这整个代码运行起来跑出来的结果是按照从小到大的顺序排列的,但是题目要求是按照原来的q[]数组的原来顺序排列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

#include <iostream>
#include <climits>

using namespace std;

// 我有两种想法,第一种时开times数组,记录q里面每个数字出现的频次
int main(void) {
int n;
cin >> n;
int q[n];
int max = 0;
for (int i = 0; i < n; i++) {
cin >> q[i];
if (max < q[i])
max = q[i];
} // 找到整个数组里面的最大值max
int times[max + 1] = {0}; // times数组,记录q里面每个数字出现的频次,没出现过就是零次
for (int i = 0; i < n; i++)
times[q[i]]++;

int res[n]; // res数组存放去重后的结果
// 将times数组里面大于等于一的元素对应的下标,就是q数组的元素
int k = 0; // k是res数组的小标
int i = 0; // i时times数组的下标
while (i < max + 1) {
if (times[i] >= 1) {
res[k] = i;
k++;
i++;
} else
i++;//这里前往别写成i++和k++
}
for (int j = 0; j < k; j++)
cout << res[j] << " ";

return 0;
}

因此要修改成这样才对

1
2
3
4
5
6
7
8
9
10
11
12
13
int res[n]; // res数组存放去重后的结果
// 将times数组里面大于等于一的元素对应的下标,就是q数组的元素
int k = 0; // k是res数组的小标
int i = 0; // i时q数组的下标
while (i < n) {
if (times[q[i]] >= 1) {
res[k] = q[i];
times[q[i]] = 0;//不让q[i]里面数值相同的数拷贝两边到res[]数组里面
k++;
i++;
} else
i++;//这里前往别写成i++和k++
}

整个程序就是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

#include <iostream>
#include <climits>

using namespace std;

// 我有两种想法,第一种时开times数组,记录q里面每个数字出现的频次
int main(void) {
int n;
cin >> n;
int q[n];
int max = 0;
for (int i = 0; i < n; i++) {
cin >> q[i];
if (max < q[i])
max = q[i];
} // 找到整个数组里面的最大值max
int times[max + 1] = {0}; // times数组,记录q里面每个数字出现的频次,没出现过就是零次
for (int i = 0; i < n; i++)
times[q[i]]++;

int res[n]; // res数组存放去重后的结果
// 将times数组里面大于等于一的元素对应的下标,就是q数组的元素
int k = 0; // k是res数组的小标
int i = 0; // i时q数组的下标
while (i < n) {
if (times[q[i]] >= 1) {
res[k] = q[i];
times[q[i]] = 0;//不让q[i]里面数值相同的数拷贝两边到res[]数组里面
k++;
i++;
} else
i++;//这里前往别写成i++和k++
}
for (int j = 0; j < k; j++)
cout << res[j] << " ";

return 0;
}

思路2

我有两种想法,第二种结合了我做过的题目,虽然最后时间复杂度也是O(n * n)

但是全当复习一遍知识也可以接受.快快写这里

先放在这里,然后…有时间再补上来

思路3

暴力的扫描,时间复杂度是O(n * n).程序运行通过了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36

#include <iostream>
#include <climits>

using namespace std;

// 我有两种想法,第二种快排或者归并排序让q变得有序,然后双指针i,j只记录第一个出现的数字(这部分就和1116:最长平台一样)
// 但是问题是这样的res[]结果数组还是按照从小到大的顺序排列的,而不是按照q[]数组原来的顺序排列的.
// 解决方法就是扫描原来顺序的q数组,对比res[]数组,每找到一个相同的,那么就输出,同时将res[]数组对应的count从0赋值成1(保证只输出一次)
// 但是这样的时间复杂度就O(n * n)
// 不过我一开始想的暴力的算法的时间复杂度一样了都是O(n * n)
int main(void) {
int n;
cin >> n;
int q[n];
int max = 0;
for (int i = 0; i < n; i++) {
cin >> q[i];
}
//暴力的扫描
int count[n] = {0};//下标和q[]数组的下标对应,count[i]等于0表示没有被输出过,等于1表示已经被输出过了
int i = 0;
int j;
for (; i < n; i++) {
j = i;
if (count[j] == 0) {
cout << q[j] << " ";
//让后面所有数值和q[j]相同的数的对应的下标对应的count数组里面的数从0变成1
for (; j < n; j++)
if (q[j] == q[i])
count[j] = 1;
}
}

return 0;
}

有意思的是,我一开始是打算将下面这段代码里面的两个for循环都写成while循环的 .

1
2
3
4
5
6
7
8
9
10
11
12
13
int count[n] = {0};//下标和q[]数组的下标对应,count[i]等于0表示没有被输出过,等于1表示已经被输出过了
int i = 0;
int j;
for (; i < n; i++) {
j = i;
if (count[j] == 0) {
cout << q[j] << " ";
//让后面所有数值和q[j]相同的数的对应的下标对应的count数组里面的数从0变成1
for (; j < n; j++)
if (q[j] == q[i])
count[j] = 1;
}
}

首先,我看出来这是嵌套的扫描两次,所以时间复杂度是O(n * n),同时我也想到了最经典的嵌套循环就是两层for循环,

但是我一开始有因为认为算法题目里面的while循环能够更加精确的控制i,j的加和减.所以采用的while循环,同时每一个花括号都加上了

包括后面if的花括号,而且每一个if都写了一个else还有else 的花括号

结果我发现我写的程序非常难懂,甚至对着i++放在拿来都要想半天怕出错

而且我意识到如果if里面最后加i++语句,配套的else里面也是写i++语句,那么就可以去掉else,只在if语句的花括号外面,也就是while循环的最后一行写i++语句

同时我又发现,既然是while循环的最后一行是i++语句,那就可以写成for循环的形式,而且for循环的形式更有利于人去读这段代码

[!IMPORTANT]

for循环把循环的i的初始值,i的test测试条件,i++,都写在一起,让人更加方便的理解和阅读代码.

while()循环则更有面向过程的味道,要你去思考每一步每一个过程都要做什么.

两者各有利弊

个人总结1

个人通过这一次从while循环改成for循环的过程中,个人理解和认为

如果在循环的过程中,无论做什么操作,都在每一轮循环的结束时候让i++,那么就用for循环

如果在循环的过程中,每一轮循环可能让i++也可能让i不变,也可能让i–也可能加一个if判断语句才能让i++这样子的情况,你就用while循环

那么同样的道理,题目1117最长平台问题就可以这样

1
2
3
4
5
6
7
8
9
10
11
12
13
int res[n]; // res数组存放去重后的结果
// 将times数组里面大于等于一的元素对应的下标,就是q数组的元素
int k = 0; // k是res数组的小标
int i = 0; // i时q数组的下标
while (i < n) {
if (times[q[i]] >= 1) {
res[k] = q[i];
times[q[i]] = 0;//不让q[i]里面数值相同的数拷贝两边到res[]数组里面
k++;
i++;
} else
i++;//这里前往别写成i++和k++
}

把这个改成后面那种形式

1
2
3
4
5
6
7
8
9
10
11
int res[n]; // res数组存放去重后的结果
// 将times数组里面大于等于一的元素对应的下标,就是q数组的元素
int k = 0; // k是res数组的小标
int i = 0; // i时q数组的下标
for (; i < n; i++) {
if (times[q[i]] >= 1) {
res[k] = q[i];
times[q[i]] = 0;//不让q[i]里面数值相同的数拷贝两边到res[]数组里面
k++;
}
}

下面整个程序也run成功了.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

#include <iostream>
#include <climits>

using namespace std;

// 我有两种想法,第一种时开times数组,记录q里面每个数字出现的频次
int main(void) {
int n;
cin >> n;
int q[n];
int max = 0;
for (int i = 0; i < n; i++) {
cin >> q[i];
if (max < q[i])
max = q[i];
} // 找到整个数组里面的最大值max
int times[max + 1] = {0}; // times数组,记录q里面每个数字出现的频次,没出现过就是零次
for (int i = 0; i < n; i++)
times[q[i]]++;

int res[n]; // res数组存放去重后的结果
// 将times数组里面大于等于一的元素对应的下标,就是q数组的元素
int k = 0; // k是res数组的小标
int i = 0; // i时q数组的下标
for (; i < n; i++) {
if (times[q[i]] >= 1) {
res[k] = q[i];
times[q[i]] = 0;//不让q[i]里面数值相同的数拷贝两边到res[]数组里面
k++;
}
}
for (int j = 0; j < k; j++)
cout << res[j] << " ";

return 0;
}

改之后的代码也运行成功了.

因为无论每一轮循环做什么操作,结束的时候都让i++,

所以对i使用for循环

而对于k来说每一轮循环结束的时候可能让k++也可能让k不变(取决于前面的if (times[q[i]] >= 1)条件,也就是说k++是间断的,找到满足条件的i使得if (times[q[i]] >= 1才能让k++.

那么就不能再对i的for循环里面嵌套对k的for循环或者在i的for循环里面直接在第三个statement3加入k++之类的语句,

应该在对i的for循环里面写对k的if判断语句让其k++或者k不变

(你可能会说,按照你之前的想法

每一轮循环可能让k++也可能让k不变,也可能让k–也可能加一个if判断语句才能让k++这样子的情况,你就用while循环

你对于k的while循环在哪里呢??

答案是我对于k的while循环就是对i的for循环的子集.仔细看看就是这样的,因为你把对k的操作和对循环变量k++或者k不变都放在for这个循环loop语句块里面了;

有意思的是,这有一点while和for循环都是if + goto语句的感觉.

因为你把对k的操作和对循环变量k++或者k不变都放在if + goto语句构成的循环块里面了,所以你要找的对于k的while循环就是这个对i的for循环,也就是同一段if + goto语句

)

个人总结2

自己脑容量完全不够用,,推荐在用纸张和笔模拟清楚,想清楚之后再敲代码,因为无论你怎么敲代码,你都只是一个翻译官的角色,真正的解题步骤还是要自己想,通过纸张和笔打草稿想出来的.

为了速度和效率和准确性,必须要用纸张和笔.

1161:转进制

个人没感觉自己代码写错了,但就是

四个测试用例,两个没过,难道是因为自己没用递归吗??

看别人用递归的例子,可能是自己没考虑整除的情况,我试了试,我整除的情况也能满足,一开始输入的x是0也能满足

不管了,下面是我的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;
void tran(int x, int m);
char tranChars[] = "0123456789ABCDEF";
int main(void)
{
int x, m;
cin >> x >> m;
// cout << tranChars[15];
tran(x, m);
return 0;
}
void tran(int x, int m)
{
// if (x == 0)
// {
// cout << 0;
// return;
// }
while (x >= m)
{
cout << tranChars[x / m];
x %= m;
}
cout << tranChars[x]; // 0到15都可以输出;
// 一开始传入的x就是0,也不用特别判断
}

下面是别人的代码,我重新敲了一遍.结果ac了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
using namespace std;
void tran(int x, int m);
char tranChars[] = "0123456789ABCDEF";
int main(void)
{
int x, m;
cin >> x >> m;
// cout << tranChars[15];
tran(x, m);
return 0;
}
void tran(int x, int m)
{
if (x == 0)//一开始的时候没看懂这里他是怎么想到特判的,,其实就是递归的终止条件,任何时候一想到递归就想到第一步就写递归的终止条件
return;
int tmp;
tmp = x / m;
tran(tmp, m);
cout << tranChars[x % m];
}

1166:求f(x,n)

个人错误:可以说是看这个表达式没完全看清楚递归的结束条件

个人错误的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <cmath>
using namespace std;
double Her(double n, double x);
int main(void)
{
double n, x;
cin >> x >> n;
printf("%.2f", Her(n, x));
return 0;
}
double Her(double n, double x)
{
if (n == 1)
return x;
else
return sqrt(n + Her(n - 1, x));
}

当 n == 1的时候,返回的是sqrt(1 + x),而不是x

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <cmath>
using namespace std;
double Her(double n, double x);
int main(void)
{
double n, x;
cin >> x >> n;
printf("%.2f", Her(n, x));
return 0;
}
double Her(double n, double x)
{
if (n == 1)
return sqrt(1 + x);
else
return sqrt(n + Her(n - 1, x));
}

1083:计算星期几

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cin>>a>>b; 

for(int i=1;i<=b;i++){

// 不能用pow(),会有过载的问题

// 只能手动乘

days*=a;

// b有几次方,就要乘几次a

days%=7;

// 为了防止过载,乘一次就要模一次7,减少数据规模 

}

之所以能在前面就模7,打个比方,9的平方,等于81,81 mod 7 = 4

如果你9 先 mod 7 = 2, 你先去掉了7的倍数的数字(反正这部分之后会因为mod 7而消失,你提前让他们消失了也是一样的效果)\

2 * 9 = 18 mod 7 = 4;

个人修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <cmath>
using namespace std;
int main(void)
{
int a, b;
cin >> a >> b;
int days = 1;
for (int i = 0; i < b; i++)
{
days *= a;
days %= 7;
}
switch (days)
{
case 0:
cout << "Sunday";
break;
case 1:
cout << "Monday";
break;
case 2:
cout << "Tuesday";
break;
case 3:
cout << "Wednesday";
break;
case 4:
cout << "Thursday";
break;
case 5:
cout << "Friday";
break;
case 6:
cout << "Saturday";
break;
}

return 0;
}

新题目

不会做1076:正常血压

http://ybt.ssoier.cn:8088/problem_show.php?pid=1076

错误代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <cmath>
using namespace std;

int main(void)
{
int n;
cin >> n;
int a, b;
int q[n] = {0};
for (int i = 0; i < n; i++)
{
cin >> a >> b;
if ((90 <= a && a <= 140) && (60 <= b && b <= 90))
q[i] = 1;
}
// 判断q[],1代表正常
// 刚好用上今天学的双指针模板,我来尝试一波
// 好像用不上双指针模板,但我这个写法也算是双指针吧,感觉差不多
int i, j;
int hour = 0;
while (i < n && j < n)
{
while (i < n && q[i] == 0)
i++;
if (i < n && j < n)
j = i;
while (j < n && q[j] == 1)
j++;
if (j - i > hour) // 这里不能加i < n && j < n,因为j最后都是1 的话,j会指向最后元素的后面一个位置,此时的j - i还是合法的
hour = j - i;
if (i < n && j < n)
i = j;
}
cout << hour;
// 答案错了,那我这题就留着做吧
return 0;
}