第一次参加蓝桥杯,不知道自己能不能有个奖。在Acwing、codeforces、蓝桥杯官网均有刷题(不多)。只会一些基础算法,希望发布自己的想法,通过大佬们的指导,得到提高(代码比较水希望别骂)。
第十五届蓝桥杯省赛C/C++ 组真题
握手问题
分析:
第一题既是签到题,又是最搞心态的题。就是两两握手,例如:A 与 B握手和B 与 A握手只计算一次,由于无序所以用组合数知识
题目:
结果:
小球反弹
分析:
这个题比赛没有写出来。运用高中知识分解成x,y轴的反复运动。
题目:
结果:
然后解出 t ,最后的答案就是sqrt(15 * 15 + 17 * 17) * t == 1100325199.77 (保留2位小数的结果)
好数
分析:
我做题习惯先从数据大小下手。1e7数据暴力用循环,时间复杂度为(O(7n)),1s能过。
代码演示:
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
cin >> n;
int res = 0;
for(int i = 1;i <= n;i++) //1 ~ n个数
{
bool flag = true;
int val = i , t = 1;
while(val)
{
if(t && val % 2 == 0) //如果当前是奇数位并且尾数是偶数
{
flag = false;
break;
}
else if(!t && val % 2 != 0) //如果当前是偶数位并且尾数是奇数
{
flag = false;
break;
}
t++;
t %= 2; //t为1时代表当前为奇数位,0为偶数位
val /= 10;
}
if(flag)res++; //如果是好数
}
cout << res;
return 0;
}
R 格式
分析:
比赛的时候我用的乘法的高精度和加法高精度
代码演示:
#include <bits/stdc++.h>
using namespace std;
int dis;
vector<int> add(vector<int> &A) //加法高精度
{
int t = 1;
for(int i = dis + 1;i < A.size();i++)
{
t += A[i];
A[i] = t % 10;
t /= 10;
}
if(t)A.push_back(t);
return A;
}
vector<int> mul(vector<int> &A , int n) //乘法高精度
{
for(int i = 0; i < n;i++) //2的n次方
{
int t = 0;
for(int j = 0;j < A.size();j++)
{
if(A[j] != 10)
{
t += A[j] * 2;
A[j] = t % 10;
t /= 10;
}
else dis = j;
}
if(t)A.push_back(t);
}
if(A[dis - 1] >= 5)A = add(A);
return A;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;
string a;
cin >> n >> a;
vector<int> A;
for(int i = a.size() - 1;i >= 0;i--)
{
if(a[i] == '.')A.push_back(10);
else A.push_back(a[i] - '0');
}
vector<int> C = mul(A , n);
for(int i = C.size() - 1;i >= dis + 1;i--)cout << C[i];
return 0;
}
数子接龙:
分析:
第一反应dfs暴搜,路径注意不交叉就行,我是这样维护交叉的
代码演示:
#include <bits/stdc++.h>
using namespace std;
const int N = 12;
int g[N][N] , kgx[N][N] , kgy[N][N]; //kg记录从那个点来的
bool st[N][N]; //记录这个点是不是走过
int d[N * N] , cnt = 0; //存放答案的位置
int n , k;
bool dfs(int x , int y , int c)
{
if(cnt == n * n - 1 && x == n && y == n)return true;
int fy[8] = {0 , 1 , 1 , 1 , 0 , -1 , -1 , -1} , fx[8] = {-1 , -1 , 0 , 1 , 1 , 1 , 0 , -1};
for(int i = 0;i < 8;i++)
{
int dx = x + fx[i] , dy = y + fy[i];
int kx1 = kgx[dx][y] , ky1 = kgy[dx][y] , kx2 = kgx[x][dy] , ky2 = kgy[x][dy];
if(!st[dx][dy] && dx > 0 && dx <= n && dy > 0 && dy <= n && g[dx][dy] == (g[x][y] + 1) % k && (kx1 != x || ky1 != dy) && (kx2 != dx || ky2 != y))
//确保没走过,且要走的点在范围内,要走的点值 == 当前点值加一对k取余,并且不会有交叉
{
st[dx][dy] = true;
d[++cnt] = i;
kgx[dx][dy] = x , kgy[dx][dy] = y;
if(dfs(dx , dy , g[dx][dy]))return true;
kgx[dx][dy] = 0 , kgy[dx][dy] = 0;
cnt--;
st[dx][dy] = false;
}
}
return false;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> k;
for(int i = 1;i <= n;i++)
{
for(int j = 1;j <= n;j++)
{
cin >> g[i][j];
}
}
st[1][1] = true;
if(dfs(1 , 1 , 0)) //我认为(1,1)这个点一定是0,因为题目说从0开始
{
for(int i = 1;i <= n * n - 1;i++)cout << d[i];
}
else cout << "-1";
return 0;
}
爬山:
分析:
这个题数据有点大如果每次都去找最大值肯定会T的,所以可以考虑使用优先队列优化
代码演示:
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
priority_queue<int , vector<int> > h;
int n , p , q;
cin >> n >> p >> q;
for(int i = 0;i < n;i++)
{
int t;
cin >> t;
h.push(t);
}
while(p != 0 || q != 0)
{
int t = h.top();
h.pop();
if(p > 0 && q > 0 && sqrt(t) < t / 2)
{
h.push(sqrt(t));
p--;
}
else if(p > 0 && q > 0)
{
h.push(t / 2);
q--;
}
else if(p > 0)
{
h.push(sqrt(t));
p--;
}
else
{
h.push(t / 2);
q--;
}
}
int res = 0;
while(h.size())
{
int t = h.top();
h.pop();
res += t;
}
cout << res;
return 0;
}
总结
感觉现在写的和比赛写的不一样,开始怀疑自己数字接龙问题里的对g[x][y] mod k写成g[x][y] mod 3了,还有宝石组合和拔河比赛没写,我怕随便写也过不了,等加入题库了再补题。以上的代码是我考试的想法不一定能AC,如有不足的地方希望大佬们能多多指导,谢谢大家!