0
点赞
收藏
分享

微信扫一扫

第十二届省赛蓝桥杯(B组)

J简文 2022-03-22 阅读 130
c++蓝桥杯

试题 A: 空间 本题总分:5 分

问题描述】 小蓝准备用 256MB 的内存空间开一个数组,数组的每个元素都是 32 位 二进制整数,如果不考虑程序占用的空间和维护内存需要的辅助空间,请问 256MB 的空间可以存储多少个 32 位二进制整数?

【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

#include <bits/stdc++.h>

using namespace std;

int main()
{
	// MB KB B b 
	int res = 256 * 1024 * 1024 / 4;
	
	cout << res << endl;
	
	// 67108864
	
	
	return 0;
} 

试题 B: 卡片 本题总分:5 分

【问题描述】 小蓝有很多数字卡片,每张卡片上都是数字 0 到 9。 小蓝准备用这些卡片来拼一些数,他想从 1 开始拼出正整数,每拼一个, 就保存起来,卡片就不能用来拼其它数了。 小蓝想知道自己能从 1 拼到多少。 例如,当小蓝有 30 张卡片,其中 0 到 9 各 3 张,则小蓝可以拼出 1 到 10, 但是拼 11 时卡片 1 已经只有一张了,不够拼出 11。 现在小蓝手里有 0 到 9 的卡片各 2021 张,共 20210 张,请问小蓝可以从 1 拼到多少? 提示:建议使用计算机编程解决问题。

【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

#include <bits/stdc++.h>

using namespace std;

const int N = 10;

int p[N];

int main()
{
	
	for (int i = 0; i < N; i ++ )	p[i] = 2021;
	
	for (int i = 1; i < 1e7; i ++ )
	{
		int x = i;
		while (x)
		{
			int t = x % 10;
			p[t] -- ;
			if (p[t] < 0)
			{
				cout << i - 1<< endl;
				return 0;
			}
			x /= 10;
		}
	}
	
	// 3181
	
	cout << "No" << endl;
	
	return 0;
} 

试题 C: 直线 本题总分:10 分

【问题描述】 在平面直角坐标系中,两点可以确定一条直线。如果有多点在一条直线上, 那么这些点中任意两点确定的直线是同一条。 给定平面上 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) 之 间的整数的点。请问这些点一共确定了多少条不同的直线。

【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 1000000, INF = 1e9;

PII p[N];
int len, l;

struct line
{
    double k;
    double d;
    int x;
    int y;
}dist[N];

bool check(double k, double d, int x, int y)
{
    for(int i = 0; i < l; i ++ )
    {
        if ( fabs(k - dist[i].k) <= 1e-9 && fabs(d - dist[i].d) <= 1e-9 &&
            x == dist[i].x && y == dist[i].y )
			return false;
    }
    return true;
}

int main()
{
	int n, m;
	n = 20, m = 21;
	
	for (int i = 0; i < n; i ++ )
		for (int j = 0; j < m; j ++ )
			p[len ++ ] = {i, j};
	
	for (int i = 0; i < len - 1; i ++ )
	{
		for (int j = i; j < len; j ++ )
	    {
	        if (i == j) continue;

	        double x1 = p[i].x, y1 = p[i].y;
	        double x2 = p[j].x, y2 = p[j].y;
	        if (x2 == x1)
	        {
	            if(check(INF, INF, x1, INF))  
	            {
	                dist[l].k = INF;
	                dist[l].d = INF;
	                dist[l].x = x1;
	                dist[l].y = INF;
	                l ++ ;
	            }
	        }
	        else if (y2 == y1)
	        {
	            if(check(INF, INF, INF, y1))  
	            {
	                dist[l].k = INF;
	                dist[l].d = INF;
	                dist[l].x = INF;
	                dist[l].y = y1;
	                l ++ ;
	            }
	        }
	        else
	        {
	            double k = (y1 - y2) / (x1 - x2);
	            double d = y1 - k * x1;
	            if (check(k, d, INF, INF))  
	            {
	                dist[l].k = k;
	                dist[l].d = d;
	                dist[l].x = INF;
	                dist[l].y = INF;
	                l ++ ;
	            }
	        }
	    }
	}
	
	
    cout << l << endl;
    // 40257
	        
	
	return 0;
}

(浮点数比较注意精度)

试题 D: 货物摆放 本题总分:10 分

【问题描述】 小蓝有一个超大的仓库,可以摆放很多货物。 现在,小蓝有 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 <bits/stdc++.h>

using namespace std;

typedef long long LL;

int main()
{
	register LL res = 0; 
	register LL n = 2021041820210418;
	
	cout << n << endl;
	
	cout << n * n << endl;
	
	for (LL i = 1; i <= n; i ++ )
		for (LL j = 1; j <= n / i; j ++ )
			if (n / (i * j * 1.0) == n / (i * j))
			{
				cout << res << endl;
				res ++ ;
			}
	cout << res << endl;	
		
	return 0;
}

没关系,有问题上百度,求约数暴力。

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 1000010;

LL gcd[N];

int main()
{
	LL n = 2021041820210418;
	int len = 0;
	LL res = 0;
	
	for (LL i = 1; i <= n / i; i ++ )
		if (n % i == 0)
		{
			gcd[len ++ ] = i;
			if (i * i != n)
				gcd[len ++ ] = n / i;
		}
		
	for (int i = 0; i < len; i ++ )
		for (int j = 0; j < len; j ++ )
			if (n % (gcd[i] * gcd[j]) == 0)
				res ++ ;
				
				
	cout << res << endl;  
	
	return 0;
}

试题 E: 路径 本题总分:15 分

【问题描述】 小蓝学习了最短路径之后特别高兴,他定义了一个特别的图,希望找到图 中的最短路径。 小蓝的图由 2021 个结点组成,依次编号 1 至 2021。 对于两个不同的结点 a, b,如果 a 和 b 的差的绝对值大于 21,则两个结点 之间没有边相连;如果 a 和 b 的差的绝对值小于等于 21,则两个点之间有一条 长度为 a 和 b 的最小公倍数的无向边相连。 例如:结点 1 和结点 23 之间没有边相连;结点 3 和结点 24 之间有一条无 向边,长度为 24;结点 15 和结点 25 之间有一条无向边,长度为 75。 请计算,结点 1 和结点 2021 之间的最短路径长度是多少。 提示:建议使用计算机编程解决问题。

【答案提交】 这是一道结果填空的题,你只需要算出结果后提交即可。本题的结果为一 个整数,在提交答案时只填写这个整数,填写多余的内容将无法得分。

#include <bits/stdc++.h>

using namespace std;

const int N = 2050, M = 2021;

int vist[N][N];

int gcd(int x, int y)
{
	return y == 0 ? x : gcd(y, x % y);
}

void floyd(int vist[][N])
{
	for (int k = 1; k <= M; k ++ )
		for (int i = 1; i <= M; i ++ )
			for (int j = 1; j <= M; j ++ )
				if (vist[i][j] > vist[i][k] + vist[k][j])
					vist[i][j] = vist[i][k] + vist[k][j];
}

int main()
{
	
	memset(vist, 0x3f, sizeof vist);
	
	
	for (int i = 1; i <= M; i ++ )
		for (int j = 1; j <= M; j ++ )
		{
			if (i == j)	vist[i][j] = 0;
			else
			{
				if (abs(i - j) <= 21)
				{
					int len = (i * j) / gcd(i, j);
					vist[i][j] = len;
					vist[j][i] = len;
				}
			}
		}
		
	floyd(vist);
	
	cout << vist[1][2021] << endl;
	
	// 10266837
	
	return 0;
}
举报

相关推荐

0 条评论