P8714 填空问题 题解
填空问题
题意
自己看(
思路
分五个小题去考虑。
问题 A
枚举门牌号,看门牌号中有多少个
点击查看代码
void SolveA () { // 问题 A int sum = 0; for (int i = 1, j; i <= 2020; i++) { // 枚举门牌号 j = i; while (j) { // 枚举每一位 sum += (j % 10 == 2); // 统计 2 的数量 j /= 10; } } cout << sum; }
输出答案:
问题 B
枚举分子和分母,判断分子分母是否互质,统计互质的分子分母对数。
点击查看代码
int gcd (int x, int y) { // 欧几里得算法求最小公因数 return (y ? gcd(y, x % y) : x); } void SolveB () { // 问题 B int sum = 0; for (int i = 1; i <= 2020; i++) { for (int j = 1; j <= 2020; j++) { // 先枚举分子分母 sum += (gcd(i, j) == 1); // 判断是否互质 } } cout << sum; }
输出答案:
问题 C
开始有难度了哟。
首先画一个草图:
经过观察,我们可以发现:对于每个整数
那么答案要求的那个数必然也在一条从下往上的红线上。
再观察一下,贯穿
再推一下,假设我们现在求的是位于
这里有一个三角形,三角形中的数的个数再加上
综上所述,求位于
点击查看代码
void SolveC () { // 问题 C int x = 20 * 2 - 1; cout << (x * (x - 1) / 2 + 20); // 套用公式 }
输出答案:
问题 D
模拟一下,有些细节,处理号闰年和星期等问题就行了。具体看代码。
点击查看代码
const int D[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 每一个月的天数 bool leap (int y) { // 判断闰年,如果是闰年则返回值为 1,否则返回值为 0 if (y % 100) { // 不是整百年 return !(y % 100 % 4); } y /= 100; // 是整百年 return !(y % 4); } bool check (int y, int m, int d) { // 判断是否已经求完了所有日子。 return !(y == 2020 && m == 10 && d == 2); // 因为包含了 2020.10.1,所以要往后一天 } void SolveD () { // 问题 D int y = 2000, m = 1, d = 1, z = 6, ans = 0; // y 为年份,m 为月份,d 为日期,z 为星期几,ans 为答案 while (check(y, m, d)) { // 判断 ans++; // 每天至少跑 1 km if (z == 1 || d == 1) { // 特殊日子 ans++; // 再跑 1 km } d++, z = z % 7 + 1; // 处理日期变更 if (m != 2 || !leap(y)) { // 不是二月或不是闰年 if (d == D[m] + 1) { // 正常处理 m++, d = 1; } } else { // 是闰二月 if (d == 30) { // 特殊处理 m++, d = 1; } } if (m == 13) { // 一年又过完了 y++, m = 1; // 新的一年! } } cout << ans; }
输出答案:
问题 E
看了一下题解区,实现也没简单到哪去,枚举一下每个二极管亮或不亮,从某一个亮着的二极管开始做一次深搜,判断是否可以只通过亮着的二极管走到所有二极管。
先建一张图我蠢了用了个邻接表,可以通过枚举二进制数来方便的枚举每种情况,统计答案即可。
点击查看代码
void pret () { // 日常犯蠢 1/1 v[0].push_back(1), v[0].push_back(5); v[1].push_back(0), v[1].push_back(2), v[1].push_back(6); v[2].push_back(1), v[2].push_back(3), v[2].push_back(6); v[3].push_back(2), v[3].push_back(4); v[4].push_back(3), v[4].push_back(5), v[4].push_back(6); v[5].push_back(0), v[5].push_back(4), v[5].push_back(6); v[6].push_back(1), v[6].push_back(2), v[6].push_back(4), v[6].push_back(5); } void dfs (int x) { // 简单 dfs if (vis[x] || !f[x]) { return ; } vis[x] = 1, num++; for (int i : v[x]) { dfs(i); } } void SolveE () { // 问题 E int sum = 0; pret(); // 预处理 for (int i = 1; i < (1 << 7); i++) { // 枚举二进制对应的十进制数 int st = 7, cnt = 0; // st 为任意的一个亮着的二极管,我就编号取最小的一个 num = 0; for (int j = 0; j < 7; j++) { // 二进制拆分 f[j] = ((i >> j) & 1), vis[j] = 0; if (f[j]) { st = min(st, j), cnt++; } } dfs(st); // 做一次深搜 sum += (num == cnt); // 如果能够找到所有发光二极管,答案加 1 } cout << sum; }
输出答案:
好了,到这里,所有小题全部解决了,总体代码
Code
点击查看完整版代码
#include <iostream> #include <vector> using namespace std; const int D[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; // 每一个月的天数 char c; vector<int> v[10]; bool vis[10], f[10]; int num; void pret () { // 日常犯蠢 1/1 v[0].push_back(1), v[0].push_back(5); v[1].push_back(0), v[1].push_back(2), v[1].push_back(6); v[2].push_back(1), v[2].push_back(3), v[2].push_back(6); v[3].push_back(2), v[3].push_back(4); v[4].push_back(3), v[4].push_back(5), v[4].push_back(6); v[5].push_back(0), v[5].push_back(4), v[5].push_back(6); v[6].push_back(1), v[6].push_back(2), v[6].push_back(4), v[6].push_back(5); } int gcd (int x, int y) { // 欧几里得算法求最小公因数 return (y ? gcd(y, x % y) : x); } bool leap (int y) { // 判断闰年,如果是闰年则返回值为 1,否则返回值为 0 if (y % 100) { // 不是整百年 return !(y % 100 % 4); } y /= 100; // 是整百年 return !(y % 4); } bool check (int y, int m, int d) { // 判断是否已经求完了所有日子。 return !(y == 2020 && m == 10 && d == 2); // 因为包含了 2020.10.1,所以要往后一天 } void dfs (int x) { // 简单 dfs if (vis[x] || !f[x]) { return ; } vis[x] = 1, num++; for (int i : v[x]) { dfs(i); } } void SolveA () { // 问题 A int sum = 0; for (int i = 1, j; i <= 2020; i++) { // 枚举门牌号 j = i; while (j) { // 枚举每一位 sum += (j % 10 == 2); // 统计 2 的数量 j /= 10; } } cout << sum; } void SolveB () { // 问题 B int sum = 0; for (int i = 1; i <= 2020; i++) { for (int j = 1; j <= 2020; j++) { // 先枚举分子分母 sum += (gcd(i, j) == 1); // 判断是否互质 } } cout << sum; } void SolveC () { // 问题 C int x = 20 * 2 - 1; cout << (x * (x - 1) / 2 + 20); // 套用公式 } void SolveD () { // 问题 D int y = 2000, m = 1, d = 1, z = 6, ans = 0; // y 为年份,m 为月份,d 为日期,z 为星期几,ans 为答案 while (check(y, m, d)) { // 判断 ans++; // 每天至少跑 1 km if (z == 1 || d == 1) { // 特殊日子 ans++; // 再跑 1 km } d++, z = z % 7 + 1; // 处理日期变更 if (m != 2 || !leap(y)) { // 不是二月或不是闰年 if (d == D[m] + 1) { // 正常处理 m++, d = 1; } } else { // 是闰二月 if (d == 30) { // 特殊处理 m++, d = 1; } } if (m == 13) { // 一年又过完了 y++, m = 1; // 新的一年! } } cout << ans; } void SolveE () { // 问题 E int sum = 0; pret(); // 预处理 for (int i = 1; i < (1 << 7); i++) { // 枚举二进制对应的十进制数 int st = 7, cnt = 0; // st 为任意的一个亮着的二极管,我就编号取最小的一个 num = 0; for (int j = 0; j < 7; j++) { // 二进制拆分 f[j] = ((i >> j) & 1), vis[j] = 0; if (f[j]) { st = min(st, j), cnt++; } } dfs(st); // 做一次深搜 sum += (num == cnt); // 如果能够找到所有发光二极管,答案加 1 } cout << sum; } int main () { // freopen("output", "w", stdout); ios::sync_with_stdio(0), cin.tie(0); cin >> c; if (c == 'A') { SolveA(); } else if (c == 'B') { SolveB(); } else if (c == 'C') { SolveC(); } else if (c == 'D') { SolveD(); } else { SolveE(); } return 0; }
点击查看简略版代码
#include<iostream> using namespace std; int ans[5] = {624, 2481215, 761, 8879, 80}; char c; int main() { cin >> c; cout << ans[c - 'A']; return 0; }
本文作者:wnsyou の blog
本文链接:https://www.cnblogs.com/wnsyou-blog/p/17384459.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步