2021蓝桥杯省赛C++B组

1550: [蓝桥杯2021初赛] 卡片
#include <bits/stdc++.h>  
using namespace std;  
int a[15] = {2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021, 2021};  
int main() {  
	int ans = 1;  
	while(1) {  
		int temp = ans;  
		while(temp != 0) {  
			int t = temp % 10; temp /= 10;  
			if(a[t] - 1 < 0) {  
				ans -= 1; cout << ans << endl;  
				return 0;  
			}  
			else a[t] --;  
		}  
		ans += 1;  
	}  
}
#include <bits/stdc++.h>  
using namespace std;  
int main() {  
	cout << 3181 << endl;  
	return 0;  
}
1551: [蓝桥杯2021初赛] 直线
#include <bits/stdc++.h>  
using namespace std;  
const int INF = 1e9;  
set<pair<double, double> > s;  
int main() {  
	int x1, y1, x2, y2;  
	for(x1 = 0; x1 < 20; x1 ++) {  
		for(y1 = 0; y1 < 21; y1 ++) {  
			for(x2 = 0; x2 < 20; x2 ++) {  
				for(y2 = 0; y2 < 21; y2 ++) {  
					if(x1 == x2) s.insert({INF, x1});  
					else {  
						double k = (double)(y2-y1)/(x2-x1);  
						double b = (double)(y1*(x2-x1)-x1*(y2-y1))/(x2-x1);  
						s.insert({k, b});  
					}   
				}  
			}  
		}  
	}  
	cout << s.size() << endl;  
	return 0;  
}
#include <bits/stdc++.h>  
using namespace std;  
int main() {  
	cout << 40257 << endl;  
	return 0;  
}
1552: [蓝桥杯2021初赛] 货物摆放
#include <bits/stdc++.h>  
using namespace std;  
typedef unsigned long long LL;  
LL n = 2021041820210418;  
LL a[3000], cnt = 0, res = 0;  
int main() {  
	for(int i = 1; i <= sqrt(n); i ++) {  
		if(n % i == 0) {  
			a[++ cnt] = i;  
			if(i*i != n) a[++ cnt] = n / i;  
		}  
	}  
	for(int l = 1; l <= cnt; l ++) {  
		for(int w = 1; w <= cnt; w ++) {  
			for(int h = 1; h <= cnt; h ++) {  
				if(a[l]*a[w]*a[h] == n) res++;  
			}  
		}  
	}  
	cout << res;  
	return 0;  
}
#include <iostream>  
using namespace std;  
int main()  
{  
	cout << 2430 << endl;  
	return 0;  
}
1553: [蓝桥杯2021初赛] 路径
#include<bits/stdc++.h>  
#define ll long longusing namespace std;  
int dist[2100];  
int g[2100][2100];  
bool st[2100];  
int gcd(int x,int y){  
	return x%y ? gcd(y, x%y) : y;  
}  
int dijkstra() {  
	memset(dist, 0x3f, sizeof dist);  
	dist[1] = 0;  
	for(int i = 0; i < 2021; i ++) {  
		int t = -1;  
		for( int j = 1; j <= 2021; j ++ ) {  
			if(!st[j] && (t == -1 || dist[t] > dist[j])) {  
				t = j;  
			}  
		}  
		st[t] = true;  
		for(int j = 1; j <= 2021; j ++) {  
			dist[j] = min(dist[j], dist[t] + g[t][j]);  
		}  
	}  
	if(dist[2021] == 0x3f3f3f3f) return -1;  
	return dist[2021];  
}  
int main() {  
	memset(g, 0x3f3f3f3f, sizeof g);  
	for(int i = 1; i <= 2021; i ++) g[i][i]=0;  
	for(int i = 1; i <= 2021; i ++) {  
		for(int j = i+1; j <= 2021 && j <= i+21; j ++) {  
			int w = i*j / gcd(i, j);  
			g[i][j] = g[j][i] = min(g[i][j], w);  
		}  
	}  
	int t = dijkstra();  
	printf("%d\n", t);  
	return 0;  
}
#include <iostream>  
using namespace std;  
int main()  
{  
	cout << 10266837 << endl;  
	return 0;  
}
1555: [蓝桥杯2021初赛] 空间
#include <bits/stdc++.h>  
using namespace std;  
int main() {  
	long long ans = 256*1024/32;  
	cout << ans*1024*8 << endl;  
	return 0;  
}
1558: [蓝桥杯2021初赛] 砝码称重
#include<bits/stdc++.h>  
using namespace std;  
typedef long long LL;  
int dp[100005]; // 为 1 是可以称出 为 0 是不可以称出  
int w[105]; // 记录每一个砝码的重量  
int main() {  
	int n; cin >> n;  
	memset(dp, 0, sizeof dp); dp[0] = 1;  
	for(int i = 1; i <= n; i ++) cin >> w[i];  
	for(int i = 1; i <= n; i ++) {  
		for(int j = 100000; j >= w[i]; j --) {  
			dp[j] = max(dp[j], dp[j-w[i]]);  
		}  
	}  
	for(int i=1;i<=n;i++){  
		for(int j = 1; j <= 100000-w[i]; j ++) {  
			dp[j] = max(dp[j], dp[j+w[i]]);  
		}  
	}  
	int ans = 0;  
	for(int i = 1; i <= 100000; i ++) ans += dp[i];  
	cout << ans << endl;  
}
1561: [蓝桥杯2021初赛] 括号序列

题意是,给定一个括号序列,要求尽可能少地添加若干括号使得括号序列变得合法,当添加完成后,会产生不同的添加结果,请问有多少种本质不同的添加结果。
首先对于本题来说,最关键的就是合法括号的定义,即对于任意前缀,左括号的数量都要大于右括号的数量,这样才可以使得括号合法。
然后就是通过计算,求解出添加最少的左括号数量,根据合法括号序列的性质,只需在每个右括号之前添加左括号使其满足前缀性质,那么显然该序列被右括号分成了,一共是右括号数量+1段,那么只需在每一段添加一个左括号即可使其合法。
定义 f[i][j] 表示对于前 i 个字符,左括号数量比右括号数量多 j 个的集合。可以分析得到状态转移方程为:
f[i][j] = f[i][j-1] + f[i-1][j+1]
从而可以通过解决本题。

#include <bits/stdc++.h>  
using namespace std;  
typedef long long LL;  
const int N = 5100, mod = 1e9 + 7;  
LL f[N][N];  
int n;  
char s[N];  
LL solve() {  
	memset(f, 0, sizeof f);  
	f[0][0] = 1;  
	for(int i = 1; i <= n; i ++) {  
		if(s[i] == '(') {  
			for(int j = 1; j <= n; j ++) {  
				f[i][j] = f[i - 1][j - 1];  
			}  
		}  
		else {  
			f[i][0] = (f[i - 1][0] + f[i - 1][1]) % mod;  
			for(int j = 1; j <= n; j ++) {  
				f[i][j] = (f[i][j - 1] + f[i - 1][j + 1]) % mod;  
			}  
		}  
	}  
	for(int i = 0; i <= n; i++) {  
		if(f[n][i]) return f[n][i];  
	}  
	return 0;  
}  
int main() {  
	scanf("%s", s + 1); n = strlen(s + 1);  
	LL x = solve();  
	reverse(s + 1, s + 1 + n);  
	for(int i = 1; i <= n; i ++) {  
		if(s[i] == '(') s[i] = ')';  
		else s[i] = '(';  
	}  
	LL y = solve();  
	cout << x * y % mod << endl;  
	return 0;  
}
1563: [蓝桥杯2021初赛] 时间显示
#include <bits/stdc++.h>  
using namespace std;  
typedef long long LL;  
int main() {  
	LL DTime = 86400000;  
	LL HTime = 3600000, MTime = 60000, STime = 1000;  
	int T; cin >> T;  
	while(T --) {  
		int H, M, S;  
		long long Time; cin >> Time;  
		Time %= DTime;  
		H = Time / HTime; Time %= HTime;  
		M = Time / MTime; Time %= MTime;  
		S = Time / STime;  
		printf("%02d:%02d:%02d\n", H, M, S);  
	}  
	return 0;  
}
1564: [蓝桥杯2021初赛] 杨辉三角形
#include<bits/stdc++.h>  
using namespace std;  
typedef long long LL;  
int a[2005][2005];  
int main() {  
	int T; cin >> T;  
	while(T --) {  
		LL N, flag = 0; cin >> N;  
		memset(a, 0, sizeof a);  
		a[0][0] = 1;  
		for(int i = 1; i < 2005; i ++) {  
			for(int j = 1; j <= i; j ++) {  
				a[i][j] = a[i-1][j] + a[i-1][j-1];  
				if(a[i][j] == N && flag == 0) {  
					cout << i*(i-1)/2+j <<endl;  
					flag = 1;  
				}  
			}  
		}  
		if(flag == 0) {  
			LL n = sqrt(N*2) + 1;  
			if(n*(n-1)/2 == N) cout << n*(n+1)/2+3 << endl;  
			else cout << N*(N+1)/2+2 << endl;  
		}  
	}  
	return 0;  
}
1565: [蓝桥杯2021初赛] 双向排序

分析题目可以得到,题目中一共设计了两种操作,一个是选定前 x 个数,使其降序,另一个是选定后 y 个数,使其升序。
对于可能出现的所有操作方式,考虑全部的情况:
1.连续出现多个操作1,即从当前位置往后全部为升序,所以只需要找到最小的那个位置,即找到连续操作 1 的最长区间,这样可以通过最长的一个区间升序,即可满足多个操作的实现。
2.连续的多个操作0,同理也是去取最长的区间进行降序的操作,从而一步实现多个操作。
3.操作0与操作1交替,需要去找两次不同操作的相交区间,操作1和2交替进行,且相比于上一次操作,本次操作的区间长度越来越短,因此相交部分也越来越短,直到两者不再相交,到这时修改将不再起作用,每次操作其实反转的也只有相交部分。故多次翻转的情况下,会使得相交的区间逐渐缩减,最后得以确定出整个的排序序列。
通过对于三种不同情况的分析,最后可以解决出本题。

#include <bits/stdc++.h>  
#define x first  
#define y second  
using namespace std;  
typedef pair<int, int> PII;  
const int N = 100010;  
int n, m, ans[N];  
PII stk[N];  
int main() {  
	scanf("%d%d", &n, &m);  
	int top = 0;  
	while(m --) {  
		int p, q; scanf("%d%d", &p, &q);  
		if (!p) {  
			while(top && stk[top].x == 0) q = max(q, stk[top --].y); //出现连续的操作1,我们取最大  
			while(top >= 2 && stk[top-1].y <= q) top -= 2; //如果当前的操作1比上一次的操作1范围大,则将上一次操作1和操作2删除  
			stk[++ top] = {0, q};//存本次最佳操作  
	}  
		else if(top) { //操作2 &&且操作1已经进行过(操作二第一个用没效果)  
			while(top && stk[top].x == 1) q = min(q, stk[top --].y);  
			while(top >= 2 && stk[top-1].y >= q) top -= 2;  
			stk[++ top] = {1, q};  
		}  
	}  
	int k = n, l = 1, r = n;  
	for(int i = 1; i <= top; i ++) {  
		if (stk[i].x == 0) {  
			while(r > stk[i].y && l <= r) ans[r --] = k -- ;  
		}  
		else {  
			while(l < stk[i].y && l <= r) ans[l ++] = k -- ;  
		}  
		if (l > r) break;  
	}  
	if(top % 2) {  
		while (l <= r) ans[l ++ ] = k -- ;  
	}  
	else {  
		while (l <= r) ans[r -- ] = k -- ;  
	}  
	for(int i = 1; i <= n; i ++) printf("%d ", ans[i]);  
	return 0;  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值