第十届蓝桥杯省赛 C++ A组

题目链接:第十届蓝桥杯省赛 C++ A组

由于很难在一个网站上模拟一次考试,下面给出自己代码运行判断正误所用到的平台:

  1. 蓝桥杯·寒假百校真题大联赛(研究生/大学A组)(第3期)
  2. 蓝桥杯练习系统

当然还会有些填空题找不到,就参照网上的答案了,题目我就直接截图拷贝了,希望不会吞


下面是题目列表

1.平方和
2.数列求值
3.最大降雨量
4.迷宫
5.RSA解密
6.完全二叉树的权值
7.外卖店优先级
8.修改数组
9.糖果

组合数问题感觉目前超出我的能力范围了,得花一段时间补补才行,现在离蓝桥杯也没多少时间了,就先空着叭

A.平方和

在这里插入图片描述
直接跳过

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int j(ll n)
{
    int flag = 0;
    while (n)
    {
        int tem = n % 10;
        if (tem == 2 || tem == 0 || tem == 1 || tem == 9)
        {
            flag = 1;
            break;
        }
        n /= 10;
    }
    return flag;
}
int main()
{
    ll res = 0;
    for (int i = 1; i <= 2019; i++)
        if (j(i))
            res += (i * i);
    cout << res;
}

B.数列求值

在这里插入图片描述
考下模运算的特性

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int main()
{
    int a1 = 1, a2 = 1, a3 = 1;
    int a4;
    int n;
    cin >> n;
    for (int i = 4; i <= 20190324; i++)
    {
        a4 = (a1 + a2 + a3) % 10000;
        a1 = a2;
        a2 = a3;
        a3 = a4;
    }
    cout << a3;
}

C.最大降雨量 在这里插入图片描述

偏向思维的题,一开始题目看错了,以为是求和,求七周每周取对应的中位数,再累加求和…那么自己结果就是46+42+38+34+30+26+22=7*34=238,看了看别人的题解答案,自己理解题目理解错了,正确答案是34,是周的中位数…有点尴尬,可以看看这位博主的思路,挺好的,我就是纯直觉hh,第十届蓝桥杯省赛 A组 C最大降雨量(思维)(作者:糖宋元明清)

D.迷宫

在这里插入图片描述
maze.txt文件下的内容

01010101001011001001010110010110100100001000101010
00001000100000101010010000100000001001100110100101
01111011010010001000001101001011100011000000010000
01000000001010100011010000101000001010101011001011
00011111000000101000010010100010100000101100000000
11001000110101000010101100011010011010101011110111
00011011010101001001001010000001000101001110000000
10100000101000100110101010111110011000010000111010
00111000001010100001100010000001000101001100001001
11000110100001110010001001010101010101010001101000
00010000100100000101001010101110100010101010000101
11100100101001001000010000010101010100100100010100
00000010000000101011001111010001100000101010100011
10101010011100001000011000010110011110110100001000
10101010100001101010100101000010100000111011101001
10000000101100010000101100101101001011100000000100
10101001000000010100100001000100000100011110101001
00101001010101101001010100011010101101110000110101
11001010000100001100000010100101000001000111000010
00001000110000110101101000000100101001001000011101
10100101000101000000001110110010110101101010100001
00101000010000110101010000100010001001000100010101
10100001000110010001000010101001010101011111010010
00000100101000000110010100101001000001000000000010
11010000001001110111001001000011101001011011101000
00000110100010001000100000001000011101000000110011
10101000101000100010001111100010101001010000001000
10000010100101001010110000000100101010001011101000
00111100001000010000000110111000000001000000001011
10000001100111010111010001000110111010101101111000

迷宫迷宫…又是迷宫…回想自己第一次遇到的算法题也是迷宫…
裸的BFS

#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct node {
	int x;
	int y;
	string s;
};
pair<int, int>p[4] = { {1, 0},{0,-1},{0,1}, {-1,0} };
char c[4] = { 'D','L','R','U' };
int vis[32][52];
int main()
{
	char a[32][52];
	for (int i = 1; i <= 30; i++)
		for (int j = 1; j <= 50; j++)
			cin >> a[i][j];
	queue<node>q;
	q.push(node{1,1,""});
	vis[1][1] = 1;
	while (!q.empty())
	{
		node tem = q.front();
		q.pop();
		if (tem.x == 30 && tem.y == 50)
		{
			cout << tem.s;
			return 0;
		}
		for (int i = 0; i < 4; i++)
		{
			int x = tem.x + p[i].first;
			int y = tem.y + p[i].second;
			if (vis[x][y] == 0 && a[x][y] == '0')
			{
				vis[x][y] = 1;
				q.push(node{ x,y,tem.s + c[i] });
			}
		}
	}
}

E.RSA解密

在这里插入图片描述
这个题是我最近几天刷题之旅最喜欢的一题!以后有时间有空的话想为这个题单独弄个文章出来
我个人建议哈,做这题前可以先试试做做洛谷上青蛙的约会这个题,在这里臭不要脸附上我自己写的一个题解青蛙的约会 (exgcd 扩展gcd),希望能对大家有所帮助
关键词:扩展欧几里得,快速乘,快速幂

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll mult_mod(ll a, ll b, ll m) // 计算 a*b mod m
{
	ll res = 0;
	while (b) {
		if (b & 1) res = (res + a) % m;  // cout<<"a="<<a<<endl;
		a = (a * 2) % m;
		b >>= 1;
	}
	return res;
}
//快速幂      
ll quick_mod(ll a, ll b, ll m)	//计算a的b次方modm
{
	ll ans = 1;
	a = a % m;
	while (b != 0)
	{
		if (b & 1) ans = mult_mod(ans, a, m) % m;//(ans*a)%m;             
		a = mult_mod(a, a, m) % m;  //a=(a*a)%m; 

		b >>= 1;
	}
	return ans;

}
ll ex_gcd(ll a, ll b, ll& x, ll& y)//扩展欧几里得 
{
	if (b == 0)
	{
		x = 1;
		y = 0;
		return a;
	}
	int r = ex_gcd(b, a % b, x, y);
	int t = x;
	x = y;
	y = t - a / b * y;
	return r;
}
int main()
{
	ll n = 1001733993063167141;
	ll p, q;
	ll d = 212353;
	ll c = 20190324;
	ll x;
	ll e;
	for (p = 2; p * p <= n; p++)//p,q的值我是先算了,就这一个解,所以才这样做
		if (n % p == 0)
		{
			q = n / p;
			break;
		}
	ll k = (p - 1) * (q - 1);
	//((d*e)%k==1)等价于(d*e+k*t==1)
	ll t;
	ex_gcd(d, k, e, t);
	//cout << e << endl;
	//考虑负数情况,取一个最小正数,反正不要是负数就行,比如可以尝试下e = (e % k + k) % k+k或者e = (e % k + k) % k+2*k都行,反正最后结果都一样
	e = (e % k + k) % k;//实际为(e%(k/gcd(d,k)) + k/gcd(d,k)) % (k/gcd(d,k))//在此题中gcd(d,k)=1,故可省略
	x = quick_mod(c, e, n);
	cout << x;
}

F.完全二叉树的权值

在这里插入图片描述
在这里插入图片描述
挺水的,前缀和罢了

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[200000];
ll s[200000];
int main()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		s[i] = s[i - 1] + a[i];
	}
	vector<ll>v;
	int i = 1;
	while (1)
	{
		ll a = i;
		ll b = i << 1;
		if (b < n)
			v.push_back(s[b - 1] - s[a - 1]);
		else
		{
			v.push_back(s[n] - s[a - 1]);
			break;
		}
		i = b;
	}
	int m = 0;
	for (int i = 0; i < v.size(); i++)
		if (v[i] > v[m])
			m = i;
	cout << m + 1;
}

G.外卖店优先级

在这里插入图片描述
在这里插入图片描述
感觉就是个模拟题…丝毫无任何算法,就是暴力…

#include<bits/stdc++.h>
using namespace std;
#define ll long long
vector<int>v[1000005];
vector<int>vt[1000005];
int pir[1000005];
int p[1000005];
int flag[1000005];
int main()
{
	int n,m,t;
	cin >> n >> m >> t;
	for (int i = 0; i < m; i++)
	{
		int ts, id;
		cin >> ts >> id;
		v[id].push_back(ts);
		vt[ts].push_back(id);
	}
	for (int i = 1; i <= n; i++)
		sort(v[i].begin(), v[i].end());
	for (int i = 0; i <= t; i++)
	{
		for (int j = 0; j < vt[i].size(); j++)
		{
			p[vt[i][j]] += 2;
			if (p[vt[i][j]] > 5)
				pir[vt[i][j]] = 1;
			flag[vt[i][j]] =1;
			
		}
		for (int i = 1; i <= n; i++)
		{
			if (!flag[i])
			{
				if (p[i])
				{
					p[i]--;
					if (p[i] < 4)
						pir[i] = 0;
				}
			}
			else flag[i] = 0;
		}
	}
	int cnt = 0;
	for (int i = 0; i <= n; i++)
		if (pir[i])
			cnt++;
	cout << cnt;
}

H.修改数组

在这里插入图片描述
这题u1s1我以三种做法做了一遍,第一次是暴力,当然会有很多数据点没过,第二次是看着别人题解写的,照着写了两遍,过了,第三次就是过了几天的今天自己写的,实在是回忆不起第二次的思路了,只记得有个很别扭的处理两侧(就是数轴上+1-1的两点)的方法,还有个莫名其妙的vis数组,干脆硬着头皮自己写了个,诶呀,对了,都是两种方法也都是用并查集写的

方法一:我自己第三次写的方法

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[100006];
int pre[1000006];
int findpre(int i)
{
	if (i == pre[i])
		return i;
	pre[i] = findpre(pre[i]);
	return pre[i];
}
int main()
{
	for (int i = 0; i < 1000006; i++)
		pre[i] = i;
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		pre[a[i]] = findpre(pre[a[i]]);
		a[i] = pre[a[i]];
		pre[a[i]] = findpre(pre[a[i] + 1]);
	}
	for (int i = 1; i < n; i++)
		cout << a[i] << ' ';
	cout << a[n];
	
}

方法二:我第二次照着别人题解写的方法…emm浏览历史没了…不知道当初是不是照着这位兄弟写的…反正和当初思路一样的
po上自己的

#include<bits/stdc++.h>
using namespace std;
int pre[1000009];
int a[100009];
int vis[1000009];
int f(int a)
{
	if (a == pre[a])
		return a;
	pre[a] = f(pre[a]);
	return (pre[a]);
}
int main()
{
	int n;
	cin >> n;
	for (int i = 0; i < 1000009; i++)
		pre[i] = i;
	for (int i = 1; i <= n; i++)
	{
		cin >> a[i];
		if(vis[a[i]])
			a[i] =f(a[i]) + 1;
		
		vis[a[i]] = 1;
		if(vis[a[i]-1])
			pre[a[i] - 1] = a[i];
		if (vis[a[i] + 1])
			pre[a[i]] = a[i] + 1;
	}
	cout << a[1];
	for (int i = 2; i <= n; i++)
		cout << ' ' << a[i];
}

I.糖果

在这里插入图片描述
在这里插入图片描述
一开始看到M这么小,就想到用状态做了,想着想着就往之前做过的记忆化搜索套了…但怎么想怎么怪,我怎么确定选哪几组呢?因为我不久前做过这个题,所以肯定自己能做出来就是说,但想了好久还是没有做出来就非常奇怪,看了看之前的提交记录,哦,暴力循环一遍所有状态啊…就很顺利写出来了,但是这个开局-1的处理啊(特别是判断最小值的时候)…我处理的真是奇葩,先po上我认为最好看的解答叭

#include<bits/stdc++.h>
using namespace std;
int a[100005];
int dp[(1<<20)+10];
int main()
{
	memset(dp, -1, sizeof dp);
	int n, m, k;
	cin >> n >> m >> k;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < k; j++)
		{
			int t;
			cin >> t;
			a[i] |= (1 << (t - 1));
		}
		dp[a[i]] = 1;
	}
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < (1 << m); j++)
		{
			if (dp[j] == -1)
				continue;
			int to = j | a[i];
			if (dp[to] == -1)
				dp[to] = dp[j] + 1;
			else
				dp[to] = min(dp[to], dp[j] + 1);
		}
	}
	cout << dp[(1 << m) - 1];
}

然后再po上我后来写的比较丑的解答hh

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[100005];
unsigned int dp[1 << 22];
int main()
{
	//我无意间发现个好玩的东西,按住Ctrl+Enter的话会向上插一个空行
	memset(dp, -1, sizeof dp);
	//cout << dp[0];
	int n, m, k;
	cin >> n >> m >> k;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < k; j++)
		{
			int t;
			cin >> t;
			t--;
			a[i] |= (1 << t);
		}
	dp[0] = 0;
	for (int i = 0; i < (1 << m); i++)
	{
		if (dp[i]<=n)
			for (int j = 0; j < n; j++)
			{
				dp[i | a[j]] = min(dp[i | a[j]], dp[i] + 1);
				//cout << (i | a[i]) << endl;
			}
	}
	cout << (int)dp[(1 << m) - 1];
}

最后一题组合数问题…着实没思路,感觉要花点时间才能搞会,那就罢了,啥都没干就写题写了好长一段时间(虽说感觉还没一个星期),但感觉效率是真的低下,从昨天开始效率就很低了…我靠我大二有这个劲头就好了呜呜呜,可惜了,现在老了都大三下了,感觉是最后一篇了叭,明天就复习下之前的东西,考完蓝桥杯还要准备下PAT…又是起步70多道题,hai,还有MIPS汇编作业,英语,夏令营材料准备,接踵而至还有各种科目的结课…

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值