202312-1 小猫分鱼
题目描述
海滩上有一堆鱼,N 只小猫来分。第一只小猫把这堆鱼平均分为 N 份,多了 i<N 个,这只小猫把多的 i 个扔入海中,拿走了一份。第二只小猫接着把剩下的鱼平均分成 N 份,又多了 i 个,小猫同样把多的 i 个扔入海中,拿走了一份。第三、第四、……,第 N 只小猫仍是最终剩下的鱼分成 N 份,扔掉多了的 i 个,并拿走一份。
编写程序,输入小猫的数量 N 以及每次扔到海里的鱼的数量 i,输出海滩上最少的鱼数,使得每只小猫都可吃到鱼。
例如:两只小猫来分鱼 N=2,每次扔掉鱼的数量为 i=1,为了每只小猫都可吃到鱼,可令第二只小猫需要拿走 1 条鱼,则此时待分配的有 3 条鱼。第一只小猫待分配的鱼有 3\times 2+1=7 条。
输入格式
总共 2 行。第一行一个整数 N,第二行一个整数 i。
保证 0<N<10;i<N 。
输出格式
一行一个整数,表示满足要求的海滩上最少的鱼数。
样例输入 1
2
1
样例输出 1
7
样例输入 2
3
1
样例输出 2
25
提示
【样例解释 2】
三只小猫来分鱼 N=3,每次扔掉鱼的数量为 i=1,为了每只小猫都可吃到鱼,可令第三只小猫需要拿走 3 条鱼(拿走 1 条和 2 条不满足要求),则此时待分配的有 10 条鱼。第二只小猫待分配的鱼有 10×3/2+1 = 16 条。第一只小猫待分配的鱼有 16×3/2+1 = 25 条。
代码解析
根据题意倒着往前推即可
#include<bits/stdc++.h>
using namespace std;
bool fish(int i, int j, int n) {
int sum = j;
for (int k = 0; k < n; k++) {
if (k != 0) {
if (sum % (n-1) != 0) {
return false;
}
sum /= (n-1);
}
sum *= n;
sum += i;
}
cout << sum;
return true;
}
int main() {
int n, i, sum;
cin >> n >> i;
for (int j = 1; ; j++) {
if (fish(i, j, n))
break;
}
return 0;
}
202312-2 单位转换
题目描述
小杨这周的数学作业是做单位转换,喜欢编程的小杨决定编程帮他解决这些问题。
小杨只学了长度单位和重量单位,具体来说:
- 长度单位包括千米(
km
)、米(m
)、毫米(mm
),它们之间的关系是:1\text{km} = 1000\text{m} = 1000000\text{mm}。 - 重量单位包括千克(
kg
)、克(g
)、毫克(mg
),它们之间的关系是:1\text{kg} = 1000\text{g} = 1000000\text{mg}。
小杨的作业只涉及将更大的单位转换为更小的单位,也就是说,小杨的作业只会包含如下题型:米转换为毫米,千米转换为毫米,千米转换为米,克转换为毫克,千克转换为毫克,千克转换为克。
现在,请你帮忙完成单位转换的程序。
输入格式
输入的第一行为一个整数,表示题目数量。
接下来 N 行,每行一个字符串,表示转换单位的题目,格式为 x 单位 1 = ? 单位 2。其中,x 为一个不超过 1000 的非负整数, 单位 1 和 单位 2 分别为两个单位的英文缩写,保证它们都是长度单位或都是重量单位,且 单位 1 比 单位 2 更大。
例如,如果题目需要你将 1\text{km} 转换为 \text{mm},则输入为 1 km = ? mm
。
保证 1\le N \le 1000。
输出格式
输出 N 行,依次输出所有题目的答案,输出时,只需要将输入中的 ? 代入答案,其余部分一字不差地输出即可。由于小杨的题目只涉及将更大的单位转换为更小的单位,并且输入的 x 是整数,因此答案一定也是整数。
例如,如果题目需要你将 1\text{km} 转换为 \text{mm},则输入为 1 km = ? mm
。则你需要输出 1 km = 1000000 mm
。
样例输入 1
2
1 km = ? mm
1 m = ? mm
样例输出 1
1 km = 1000000 mm
1 m = 1000 mm
样例输入 2
5
100 m = ? mm
1000 km = ? m
20 kg = ? g
200 g = ? mg
0 kg = ? mg
样例输出 2
100 m = 100000 mm
1000 km = 1000000 m
20 kg = 20000 g
200 g = 200000 mg
0 kg = 0 mg
代码解析
直接使用
cin
输入,避免之后还需要字符串分割,输入的时候可以将 ?和 = 都忽略掉因为题目中说了只能是“大转小”,所以当第一个单位是 m 或者 g 的时候,只能是转到 mm 或者 mg,当第二个单位是 m 或者 g 的时候只能是 km 转 m 或者 kg 转 g,所以这两种可能性都是直接乘 1000,除此之外肯定是 kg 转 mg,或者 km 转 mm
void get(int n, string s1, string s2) {
int m;
if (s1 == "m" || s1 == "g")
m = 1000 * n;
else if (s2 == "m" || s2 == "g")
m = 1000 * n;
else
m = 1000000 * n;
cout << n << ' '+s1+" = " << m << ' '+s2 << endl;
}
观察函数发现代码有些繁琐,而且不管是 m 还是 g,他都是长度为 1 的字符串,所以优化后:
#include<bits/stdc++.h>
using namespace std;
void get(int n, string s1, string s2) {
int m;
if (s1.size() == 1 || s2.size() == 1)
m = 1000 * n;
else
m = 1000000 * n;
cout << n << ' '+s1+" = " << m << ' '+s2 << endl;
}
int main() {
int n;
cin >> n;
while (n--) {
int a;
string s1, s2;
cin >> a >> s1 >> s2 >> s2 >> s2;
get(a, s1, s2);
}
return 0;
}
202309-1 小杨的储蓄
题目描述
小杨共有 N 个储蓄罐,编号从 0 到 N-1。从第 1 天开始,小杨每天都会往存钱罐里存钱。具体来说,第 i 天他会挑选一个存钱罐 a_i,并存入 i 元钱。过了 D 天后,他已经忘记每个储蓄罐里都存了多少钱了,你能帮帮他吗?
输入格式
输入 2 行,第一行两个整数 N,D;第二行 D 个整数,其中第 i 个整数为 {a_i}(保证 0 \le a_i \le N-1)。
每行的各个整数之间用单个空格分隔。
保证 1 \le N \le 1,000;1 \le D \le 1,000。
输出格式
输出 N 个用单个空格隔开的整数,其中第 i 个整数表示编号为 i-1 的存钱罐中有多少钱(i=1, \cdots ,N)。
样例输入 1
2 3
0 1 0
样例输出 1
4 2
样例输入 2
3 5
0 0 0 2 0
样例输出 2
11 0 4
提示
【样例解释 1】
小杨在第 1 天、第 2 天、第 3 天分别向 0 号、 1 号、 0 号存钱罐存了 1 元钱、 2 元钱、 3 元钱,因此 0 号存钱罐有 1+3=4 元钱,而 1 号存钱罐有 2 元钱。
代码解析
第
i
天会给m
号存钱罐投入i
元,所以我们只需要给money[m]
加上i
即可,最后输出的时候注意,下标是从 0 开始的
#include<iostream>
using namespace std;
int main() {
int N, D, money[1001] = {0};
cin >> N >> D;
for (int i = 1; i <= D; i++) {
int m;
cin >> m;
money[m] += i;
}
for (int i = 1; i <= N; i++)
cout << money[i-1] << ' ';
return 0;
}
202309-2 进制判断
题目描述
N 进制数指的是逢 N 进一的计数制。例如,人们日常生活中大多使用十进制计数,而计算机底层则一般使用二进制。除此之外,八进制和十六进制在一些场合也是常用的计数制(十六进制中,一般使用字母 A 至 F 表示十至十五)。
现在有N个数,请你分别判断他们是否可能是二进制、八进制、十进制、十六进制。例如,15A6F
就只可能是十六进制,而 1011
则是四种进制皆有可能。
输入格式
输入的第一行为一个十进制表示的整数 N。接下来 N 行,每行一个字符串,表示需要判断的数。保证所有字符串均由数字和大写字母组成,可能以 0 开头。保证不会出现空行。
保证 1 \le N \le 1000,保证所有字符串长度不超过 10。
输出格式
输出 N 行,每行 4 个数,用空格隔开,分别表示给定的字符串是否可能表示一个二进制数、八进制数、十进制数、十六进制数。使用 1 表示可能,使用 0 表示不可能。
例如,对于只可能是十六进制数的 15A6F
,就需要输出 0 0 0 1
;而对于四者皆有可能的 1011
,则需要输出 1 1 1 1
。
样例输入 1
2
15A6F
1011
样例输出 1
0 0 0 1
1 1 1 1
样例输入 2
4
1234567
12345678
FF
GG
样例输出 2
0 1 1 1
0 0 1 1
0 0 0 1
0 0 0 0
代码解析
可以用笨办法,定义
bool
变量k2, k8, k10, k16
,当遇到不同范围字符,做好标记就可以
#include<iostream>
#include<string>
using namespace std;
void check(string s) {
bool k2=1, k8=1, k10=1, k16=1;
for (int i = 0; i < s.size(); i++) {
if (s[i] >= '2' && s[i] <= '9' || s[i] >= 'A')
k2 = 0;
if (s[i] >= '8' && s[i] <= '9' || s[i] >= 'A')
k8 = 0;
if (s[i] >= 'A')
k10 = 0;
if (s[i] >= 'G')
k16 = 0;
}
cout << k2 << ' ' << k8 << ' ' << k10 << ' ' << k16 << endl;
}
int main() {
int n;
cin >> n;
while (n--) {
string s;
cin >> s;
check(s);
}
return 0;
}
202306-1 春游
题目描述
老师带领同学们春游。已知班上有 N 位同学,每位同学有从 0 到 N-1 的唯一编号。到了集合时间,老师确认是否所有同学都到达了集合地点,就让同学们报出自己的编号。到达的同学都会报出自己的编号,不会报出别人的编号,但有的同学很顽皮,会多次报出。你能帮老师找出有哪些同学没有到达吗 ?。
输入格式
输入包含 2 行。第一行包含两个整数 N 和 M,表示班级有 N 位同学,同学们共有 M 次报出编号。约定 2 \le N,M \le 1000。
第二行包含 M 个整数,分别为 M 次报出的编号。约定所有编号是小于 N 的非负整数。
输出格式
输出一行。如果所有同学都到达,则输出 N;否则由小到大输出所有未到达的同学编号,空格分隔。
样例输入 1
3 3
0 2 1
样例输出 1
3
样例输入 2
3 5
0 0 0 0 0
样例输出 2
1 2
代码解析
使用数组来标记已经报过数的同学编号,每次报数
n
,我们就将student[n]
标记为 1需要一个
bool
变量all
来标记是否全部到达
#include<iostream>
using namespace std;
bool student[1001];
int main() {
int N, M, n;
cin >> N >> M;
for (int i = 0; i < M; i++) {
cin >> n;
student[n] = 1;
}
bool all = true;
for (int i = 0; i < N; i++) {
if (!student[i]) {
cout << i << ' ';
all = false;
}
}
if (all) cout << N;
return 0;
}
202306-2 密码合规
题目描述
网站注册需要有用户名和密码,编写程序以检查用户输入密码的有效性。合规的密码应满足以下要求 :。
- 只能由 \texttt a \sim \texttt z 之间 26 个小写字母、\texttt A \sim \texttt Z 之间 26 个大写字母、0 \sim 9 之间 10 个数字以及
!@#$
四个特殊字符构成。 - 密码最短长度 :6 个字符,密码最大长度 :12 个字符。
- 大写字母,小写字母和数字必须至少有其中两种,以及至少有四个特殊字符中的一个。
输入格式
输入一行不含空格的字符串。约定长度不超过 100。该字符串被英文逗号分隔为多段,作为多组被检测密码。
输出格式
输出若干行,每行输出一组合规的密码。输出顺序以输入先后为序,即先输入则先输出。
样例输入 1
seHJ12!@,sjdkffH$123,sdf!@&12HDHa!,123&^YUhg@!
样例输出 1
seHJ12!@
sjdkffH$123
提示
【样例 1 解释】
输入被英文逗号分为了四组被检测密码:seHJ12!@
、sjdkffH$123
、sdf!@&12HDHa!
、123&^YUhg@!
。其中 sdf!@&12HDHa!
长度超过 12 个字符,不合规;123&^YUhg@!
包含四个特殊字符之外的字符不合规。
代码解析
定义
check
函数来判断一个密码是否合规
check
函数中,定义up, down, digit, chr
四个bool
变量分别判断字符串中是否含有大写、小写、数字、特殊符号,遍历的过程中如果有就标记为1
,当全部遍历完成之后判断up + low + digit >= 2
表示三个中至少有两个,再判断chr
是否为真就可以拼接分割密码的时候,注意最后一个密码不是以逗号
,
结尾的,所以最后需要再判断一下
#include<iostream>
#include<string>
using namespace std;
bool check(string s) {
bool up = 0, low = 0, digit = 0, chr = 0;
if (s.size() < 6 || s.size() > 12)
return false;
for (int i = 0; i < s.size(); i++) {
if (s[i] >= 'a' && s[i] <= 'z')
low = 1;
else if (s[i] >= 'A' && s[i] <= 'Z')
up = 1;
else if (s[i] >= '0' && s[i] <= '9')
digit = 1;
else if (s[i]=='!'||s[i]=='@'||s[i]=='#'||s[i]=='$')
chr = 1;
else
return false;
}
if (up + low + digit >= 2 && chr)
return true;
else
return false;
}
int main() {
string s, password = "";
cin >> s;
for (int i = 0; i < s.size(); i++) {
if (s[i] == ',') {
if (check(password))
cout << password << endl;
password = "";
} else {
password += s[i];
}
}
if (check(password))
cout << password << endl;
return 0;
}