目录
1550: [蓝桥杯2021初赛] 卡片
1551: [蓝桥杯2021初赛] 直线
1552: [蓝桥杯2021初赛] 货物摆放
1553: [蓝桥杯2021初赛] 路径
1555: [蓝桥杯2021初赛] 空间
1563: [蓝桥杯2021初赛] 时间显示
题目描述
小蓝有很多数字卡片,每张卡片上都是数字0 到9。
小蓝准备用这些卡片来拼一些数,他想从1 开始拼出正整数,每拼一个,就保存起来,卡片就不能用来拼其它数了。
小蓝想知道自己能从1 拼到多少。
例如,当小蓝有30 张卡片,其中0 到9 各3 张,则小蓝可以拼出1 到10,但是拼11 时卡片1 已经只有一张了,不够拼出11。
现在小蓝手里有0 到9 的卡片各2021 张,共20210 张,请问小蓝可以从1拼到多少?
提示:建议使用计算机编程解决问题。
答案:3181
#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最后用尽的那一数是多少就是要求的结果
#include
using 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;
}
题目描述
在平面直角坐标系中,两点可以确定一条直线。
如果有多点在一条直线上,那么这些点中任意两点确定的直线是同一条。
给定平面上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) 之间的整数的点。
请问这些点一共确定了多少条不同的直线。
答案:40257
思路:用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);
//double b = (p[i].y * (p[j].x - p[i].x) - p[i].x * (p[j].y - p[i].y)) / (p[j].x - p[i].x);
s.insert(make_pair(k, b));
}
}
cout << m + n + s.size() << endl;
return 0;
}
题目描述
小蓝有一个超大的仓库,可以摆放很多货物。
现在,小蓝有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 位数字)时,总共有多少种
方案?
提示:建议使用计算机编程解决问题。
答案:2430
思路:先求出它的所有因子,然后循环遍历即可
#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
//核心:通过判断三个数出现的组合次数。
#include
using 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;
}
题目描述
小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图中的最短路径。
小蓝的图由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;
}
题目描述
小蓝准备用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
题目描述
小蓝要和朋友合作开发一个时间显示的网站。
在服务器上,朋友已经获取了当前的时间,用一个整数表示,值为从 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
#include
using 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;
}