目录
1550: [蓝桥杯2021初赛] 卡片
1551: [蓝桥杯2021初赛] 直线
1552: [蓝桥杯2021初赛] 货物摆放
1553: [蓝桥杯2021初赛] 路径
1555: [蓝桥杯2021初赛] 空间
1563: [蓝桥杯2021初赛] 时间显示
1550: [蓝桥杯2021初赛] 卡片
题目描述
小蓝有很多数字卡片,每张卡片上都是数字0 到9。
小蓝准备用这些卡片来拼一些数,他想从1 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。
小蓝想知道自己能从1 拼到多少。
例如,当小蓝有30 张卡片,其中0 到9 各3 张,则小蓝可以拼出1 到10,但是拼11 时卡片1 已经只有一张了,不够拼出11。
现在小蓝手里有0 到9 的卡片各2021 张,共20210 张,请问小蓝可以从1拼到多少?
提示:建议使用计算机编程解决问题。
#include#include #include using namespace std; int main() { int arr[10]; for (int i = 0; i < 10; i++) { arr[i] = 2021; // 0 - 9 的卡片各2021张 } for (int i = 1; ; i++) { int x = i; while(x != 0) { if(arr[x % 10] == 0) { //当有一张卡片的数量剩余为0时候 输出 i-1并退出 cout << i - 1; return 0; } arr[x % 10]--;//每张卡片数量减少1 x /= 10; } } return 0; }
思路:因为1是排在最前面的,即1是最先进行消耗完毕的,所以我们只要记录下来1最后用尽的那一数是多少就是要求的结果
#includeusing namespace std; int main() { int sum = 2021, ans = 0; for (int i = 1; i < 20210; i++) { int temp = i; while(temp != 0) { if(temp % 10 == 1 && sum > 0) { sum--; } temp /= 10; } if(sum == 0){ ans = i; break; } } cout << ans; }
1551: [蓝桥杯2021初赛] 直线
题目描述
在平面直角坐标系中,两点可以确定一条直线。
如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。
给定平面上2 × 3 个整点{(x, y)|0 ≤ x < 2, 0 ≤ y < 3, x ∈ Z, y ∈ Z},
即横坐标是0 到1 (包含0 和1) 之间的整数、纵坐标是0 到2 (包含0 和2) 之间的整数的点。
这些点一共确定了11 条不同的直线。
给定平面上20 × 21 个整点{(x, y)|0 ≤ x < 20, 0 ≤ y < 21, x ∈ Z, y ∈ Z},
即横坐标是0 到19 (包含0 和19) 之间的整数、纵坐标是0 到20 (包含0 和20) 之间的整数的点。
请问这些点一共确定了多少条不同的直线。
思路:用set去重 找斜率和截距
#include#include using namespace std; const int N = 500; set > s;//存斜率和截距 去重 class Node { public: double x, y;// i横坐标, j纵坐标 }; int main() { Node p[N]; int cnt = 0; int m = 20, n = 21; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { p[cnt].x = i; p[cnt].y = j; cnt++; } } for (int i = 0; i < cnt; i++) { for (int j = 0; j < cnt; j++) { if (p[i].x == p[j].x || p[i].y == p[j].y) //x轴或者y轴 continue; double k = (p[j].y - p[i].y) / (p[j].x - p[i].x); double b = (p[j].x * p[i].y - p[j].y * p[i].x) / (p[j].x - p[i].x); s.insert(make_pair(k, b)); } } cout << m + n + s.size() << endl; return 0; }
1552: [蓝桥杯2021初赛] 货物摆放
题目描述
小蓝有一个超大的仓库,可以摆放很多货物。
现在,小蓝有n 箱货物要摆放在仓库,每箱货物都是规则的正方体。
小蓝规定了长、宽、高三个互相垂直的方向,每箱货物的边都必须严格平行于长、宽、高。
小蓝希望所有的货物最终摆成一个大的立方体。即在长、宽、高的方向上分别堆L、W、H 的货物,满足n = L × W × H。
给定n,请问有多少种堆放货物的方案满足要求。
例如,当n = 4 时,有以下6 种方案:1×1×4、1×2×2、1×4×1、2×1×2、2×2×1、4×1×1。
请问,当n = 2021041820210418 (注意有16 位数字)时,总共有多少种
方案?
提示:建议使用计算机编程解决问题。
思路:先求出它的所有因子,然后循环遍历即可
#include#include using namespace std; typedef long long ll; int main() { ll n = 2021041820210418; ll cnt = 0; vector v; for (ll i = 1; i <= n / i; i++) { if (n % i == 0) { v.push_back(i); if (i * i != n) v.push_back(n / i); } } for (ll i = 0; i < v.size(); i++) { for (ll j = 0; j < v.size(); j++) { for (ll k = 0; k < v.size(); k++) { if (v[i] * v[j] * v[k] == n) cnt++; } } } cout << cnt; return 0; }
思路2
//核心:通过判断三个数出现的组合次数。 #includeusing namespace std; typedef long long LL; int main() { LL n = 2021041820210418; LL i, j, k; int res = 0; for (i = 1; i * i * i <= n; i++) if (n % i == 0) for (j = i; i * j * j <= n; j++) if (n / i % j == 0) { k = n / i / j; if (i == j && i == k) res++; if (i == j || i == k || j == k) res += 3; else res += 6; } printf("%d", res); return 0; }
1553: [蓝桥杯2021初赛] 路径
题目描述
小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图中的最短路径。
小蓝的图由2021 个结点组成,依次编号1 至2021。
对于两个不同的结点a, b,如果a 和b 的差的绝对值大于21,则两个结点之间没有边相连;
如果a 和b 的差的绝对值小于等于21,则两个点之间有一条长度为a 和b 的最小公倍数的无向边相连。
例如:结点1 和结点23 之间没有边相连;结点3 和结点24 之间有一条无向边,长度为24;
结点15 和结点25 之间有一条无向边,长度为75。
请计算,结点1 和结点2021 之间的最短路径长度是多少。
提示:建议使用计算机编程解决问题。
答案:10266837
思路:这是一道最短路的简化题 用floyd或者dijkstra都可,但因为是一道填空题 用floyd跑也可以,不过大概需要半分钟的时间
floyd算法
#include#include using namespace std; const int MAXN = 2500; int Graph[MAXN][MAXN];//邻接矩阵 int gcd(int a, int b)//最大公约数 { return b == 0 ? a : gcd(b, a % b); } void init() { memset(Graph, 0x3f, sizeof(Graph)); for (int i = 1; i <= 2021; i++) { for (int j = 1; j <= 2021; j++) { if (abs(i - j) <= 21) { Graph[i][j] = Graph[j][i] = (i * j) / gcd(i, j); } } } } void floyd()//时间复杂度比较大 要跑半分钟左右 { for (int k = 1; k <= 2021; k++) { for (int i = 1; i <= 2021; i++) { for (int j = 1; j <= 2021; j++) { Graph[i][j] = min(Graph[i][j], Graph[i][k] + Graph[k][j]); } } } } int main() { init(); floyd(); cout << Graph[1][2021]; }
dijkstra算法
#include#include #include using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 2500; int Graph[MAXN][MAXN], dis[MAXN]; bool vis[MAXN]; int gcd(int a, int b)//最大公约数 { return b == 0 ? a : gcd(b, a % b); } void init() { memset(Graph, 0x3f, sizeof(Graph)); for (int i = 1; i <= 2021; i++) { for (int j = 1; j <= 2021; j++) { if (i == j) Graph[i][j] = 0; else if (abs(j - i) > 21) Graph[i][j] = Graph[j][i] = INF; else Graph[i][j] = Graph[j][i] = i * j / gcd(i, j); } } } void dijkstra() { memset(dis, 0x3f, sizeof(dis)); dis[1] = 0; for (int i = 1; i <= 2021; i++) { int t = -1; for (int j = 1; j <= 2021; j++) { if (!vis[j] && (t == -1 || dis[j] < dis[t])) t = j; } vis[t] = true; for (int j = 1; j <= 2021; j++) { if (!vis[j]) { dis[j] = min(dis[j], dis[t] + Graph[t][j]); } } } } int main() { init(); dijkstra(); cout << dis[2021] << endl; return 0; }
1555: [蓝桥杯2021初赛] 空间
题目描述
小蓝准备用256MB 的内存空间开一个数组,数组的每个元素都是32 位二进制整数。
如果不考虑程序占用的空间和维护内存需要的辅助空间,请问256MB 的空间可以存储多少个32 位二进制整数?
根据换算关系:
B代表字节,b代表位,即32位4个字节
1MB=1024KB, 1KB=1024B, 1B(字节)=8b=8位
由题意知:
256MB=256×1024KB=256×1024×1024B=256×1024×1024×8b=256×1024×1024×8位
一个元素 = 32位
可以储存(个)=256×1024×1024×8/32(个)
答案:256 * 1024 * 1024 * 8 / 32 = 67108864
1563: [蓝桥杯2021初赛] 时间显示
题目描述
小蓝要和朋友合作开发一个时间显示的网站。
在服务器上,朋友已经获取了当前的时间,用一个整数表示,值为从 19701970 年 11 月 11 日 00:00:0000:00:00 到当前时刻经过的毫秒数。
现在,小蓝要在客户端显示出这个时间。小蓝不用显示出年月日,只需要显示出时分秒即可,毫秒也不用显示,直接舍去即可。
给定一个用整数表示的时间,请将这个时间对应的时分秒输出。
输入描述
输入一行包含一个整数,表示时间。
输出描述
输出时分秒表示的当前时间,格式形如 HH:MM:SS,其中 HH 表示时,值为 00 到 2323,MM 表示分,值为 00 到 5959,SS 表示秒,值为 00 到 5959。时、分、秒 不足两位时补前导 00。
输入输出样例
输入样例1
46800999
输出样例 1
13:00:00
输入样例2
1618708103123
输出样例2
01:08:23
思路:模拟即可,需要注意的是1s = 1000ms
#includeusing namespace std; typedef long long ll; int main() { ll time, hour, minute, seconds; cin >> time; time = time / 1000;//转化为秒 hour = (time / 3600) % 24; minute = (time / 60) % 60; seconds = time % 60; printf("%02lld:%02lld:%02lld", hour, minute, seconds); return 0; }



