202509-1 优美的数字
题目描述
如果一个正整数在十进制下的所有数位都相同,小 A 就会觉得这个正整数很优美。例如,正整数 的数位都是 ,所以 是优美的。正整数 的数位都是 ,所以 是优美的。正整数 的数位不都相同,所以 并不优美。
小 A 想知道不超过 的正整数中有多少优美的数字。你能帮他数一数吗?
输入格式
一行,一个正整数 。
输出格式
一行,一个正整数,表示不超过 的优美正整数的数量。
样例输入 1
6
样例输出 1
6
样例输入 2
2025
样例输出 2
28
提示
对于所有测试点,保证 。
代码解析
对于范围内的每一个数字进行数位剥离,重点是要判断他的每一位是否都相同,所以我们可以事先把他的各位保存到 t 中,然后在数位剥离的过程中判断当前末尾数是否等于 t,如果不相等则修改 flag 为 flase;
注意根据题意,10以内的数字都是优美数。
#include<bits/stdc++.h>using namespace std;int main() {
int n, cnt = 0; cin >> n; for (int i = 1; i <= n; i++) { int x = i, t = x % 10; bool flag = true; while (x) { if (t != x % 10) { flag = false; break; } x /= 10; } if (flag || i < 10) cnt++; } cout << cnt;
return 0;}
202509-2 菱形
题目描述
小 A 想绘制一个菱形。具体来说,需要绘制的菱形是一个 行 列的字符画, 是一个大于 的奇数。菱形的四个顶点依次位于第 行、第 列、第 行、第 列的正中间,使用 #
绘制。相邻顶点之间也用 #
连接。其余位置都是 .
。
例如,一个 行 列的菱形字符画是这样的:
..#...#.#.#...#.#.#...#..
给定 ,请你帮小 A 绘制对应的菱形。
输入格式
一行,一个正整数 。
输出格式
输出共 行,表示对应的菱形。
样例输入 1
3
样例输出 1
.#.#.#.#.
样例输入 2
9
样例输出 2
....#.......#.#.....#...#...#.....#.#.......#.#.....#...#...#.....#.#.......#....
提示
对于所有测试点,保证 并且 为奇数。
代码解析
看似复杂,实际只需要找出来 # 的规律即可,这里可以分为上半部分和下半部分分别绘制,以九行为例:
第 1 行 # 的位置:5(5+0 和 5-0)
第 2 行 # 的位置:4、6(5+1 和 5-1)
第 3 行 # 的位置:3、7(5+2 和 5-2)
第 i 行 # 的位置: 5+(i - 1) 和 5 - (i - 1),这里的 5 就是 9/2+1
#include<bits/stdc++.h>using namespace std;int main() {
int n; cin >> n; for (int i = 1; i <= n/2+1; i++) { for (int j = 1; j <= n; j++) if (j == n/2+1 + (i-1) || j == n/2+1 - (i-1)) cout << '#'; else cout << '.'; cout << endl; } // 下半部分 i 逆序即可,内层不变 for (int i = n/2; i >= 1; i--) { for (int j = 1; j <= n; j++) if (j == n/2+1 + (i-1) || j == n/2+1 - (i-1)) cout << '#'; else cout << '.'; cout << endl; }
return 0;}
202506-1 数三角形
题目描述
直角三角形有两条直角边与一条斜边,设两条直角边的长度分别为 ,则直角三角形的面积为 。
请你计算当直角边长 均取不超过 的正整数时, 有多少个不同的面积为整数的直角三角形。直角边长分别为 和 的两个直角三角形相同,当且仅当 , 或者 , 。
输入格式
一行,一个整数 ,表示直角边长的最大值。
输出格式
输出一行,一个整数,表示不同的直角三角形数量。
样例输入 1
3
样例输出 1
3
样例输入 2
5
样例输出 2
9
提示
对于所有测试点,保证 。
代码解析
透过题目看本质,我们需要让两条直角边从 1 开始到 n 依次去枚举,枚举的过程中需要注意两个点:第一、两条边的乘积需要是 2 的倍数,第二、枚举的过程中不能有重复的数字,比如 2、5 和 5、2。
#include<bits/stdc++.h>using namespace std;int main() {
int n, cnt = 0; cin >> n; for (int i = 1; i <= n; i++) // 从 i 开始枚举,保证 i 和 j 的组合不重复 for (int j = i; j <= n; j++) if (i * j % 2 == 0) cnt++;
cout << cnt;
return 0;}
202506-2 幂和数
题目描述
对于正整数 ,如果 可以表为两个 的次幂之和,即 ( 均为非负整数),那么称 为幂和数。
给定正整数 ,请你求出满足 的整数 中有多少个幂和数。
输入格式
一行,两个正整数 ,含义如上。
输出格式
输出一行,一个整数,表示 之间幂和数的数量。
样例输入 1
2 8
样例输出 1
6
样例输入 2
10 100
样例输出 2
20
提示
对于所有测试点,保证 。
代码解析 1
题目需要找到范围内满足 的数字,这道题可以用二进制的思路来简化代码,我们知道 的二进制中只有一个 1 后面全是 0(如:8、16、32),那么满足这个条件的数字 n 分为两种(以八位二进制举例):
- (0000 1000) + (0001 0000) => (0001 1000) n 的二进制中有两个 1
- (0000 1000) + (0000 1000) => (0001 0000) n 的二进制中只有一个 1
所以我们只需要找出范围内二进制中 1 的个数为 1 或者 2 的数即可(1是特例,排除在外)
#include<bits/stdc++.h>using namespace std;int main() {
int l, r, cnt = 0; cin >> l >> r; for (int i = l; i <= r; i++) { if (i == 1) continue; int cnt1 = 0, n = i; // 计算 n 的二进制中 1 的个数 while (n) { if (n % 2 == 1) cnt1++; n /= 2; } if (cnt1 == 2 || cnt1 == 1) cnt++; } cout << cnt;
return 0;}
代码解析 2
如果还没有掌握二进制的知识,则需要枚举法,这里我们枚举 X 和 Y 作为题目中的 和 ,为了防止重复的 X 和 Y 组合,可以让 Y 从 X 开始枚举
#include<bits/stdc++.h>using namespace std;int main() {
int l, r, cnt = 0; cin >> l >> r; for (int i = l; i <= r; i++) for (int X = 1; X<= i; X*=2) for (int Y = X; Y <= i; Y*=2) if (X + Y == i) cnt++; cout << cnt;
return 0;}
202503-1 等差矩阵
题目描述
小 A 想构造一个 行 列的矩阵,使得矩阵的每一行与每一列均是等差数列。小 A 发现,在矩阵的第 行第 列填入整数 ,得到的矩阵能满足要求。你能帮小 A 输出这个矩阵吗?
输入格式
一行,两个正整数 。
输出格式
共 行,每行 个由空格分割的整数,表示小 A 需要构造的矩阵。
样例输入 1
3 4
样例输出 1
1 2 3 42 4 6 83 6 9 12
提示
对于所有测试点,保证 。
代码解析
按照题目中给出的规律打印 n 行 m 列的矩阵即可,不需要用到数组相关知识。
#include<bits/stdc++.h>using namespace std;int main() {
int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) cout << i * j << ' '; cout << endl; }
return 0;}
202503-2 时间跨越
题目描述
假设现在是 年 月 日 时而 小时后是 年 月 日 时,对于给定的 ,小杨想请你帮他计算出对应的 是多少。
输入格式
输入包含五行,每行一个正整数,分别代表 。
输出格式
输出四个正整数,代表 。
样例输入 1
2008228231
样例输出 1
2008 2 29 0
提示
对于全部数据,保证有 ,,,,。数据保证为合法时间。
闰年判断规则
- 普通闰年:年份能被 整除,但不能被 整除。
- 世纪闰年:年份能被 整除。
满足以上任意一条规则的年份就是闰年,否则是平年。
代码解析
代码看起来比较多,实际原理就是一小时一小时的去加,循环 k 次,简单的模拟这个过程即可,注意其中的小时、日、月的进位,以及大小月和闰年的判断。
#include<bits/stdc++.h>using namespace std;int main() {
int y, m, d, h, k, max_day; cin >> y >> m >> d >> h >> k; for (int i = 1; i <= k; i++) { h++; if (h > 23) { h = 0; d++; switch (m) { case 1: case 3: case 5: case 7: case 8: case 10: case 12: max_day = 31; break; case 4: case 6: case 9: case 11: max_day = 30; break; case 2: if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) max_day = 29; else max_day = 28; break; } if (d > max_day) { d = 1; m++; if (m > 12) { m = 1; y++; } } } } cout << y << ' ' << m << ' ' << d << ' ' << h;
return 0;}
若已经学了数组的话,可以把每月的天数存到数组里,只需要单独判断二月即可,上面解法中的
switch
结构就可以不用了。
#include<bits/stdc++.h>using namespace std;int main() {
int y, m, d, h, k, max_day; int day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; cin >> y >> m >> d >> h >> k; for (int i = 1; i <= k; i++) { h++; if (h > 23) { h = 0; d++; if (y % 4 == 0 && y % 100 != 0 || y % 400 == 0) day[2] = 29; else day[2] = 28; if (d > day[m]) { d = 1; m++; if (m > 12) { m = 1; y++; } } } } cout << y << ' ' << m << ' ' << d << ' ' << h;
return 0;}