望眉目有山河,清澈明朗;愿胸中有丘壑,一往无前。 |

chfychin

园龄:1年7个月粉丝:3关注:3

第十五届蓝桥杯软件赛省赛C/C++B 组题解

目录

试题 A: 握手问题

本题总分:5

思路:组合计数,用为 50 个人握手的总方案数 C502 ,减去七个人彼此没有握手的方案数 C72 即为答案。

握手问题
#include <bits/stdc++.h>
#define int long long
#define db long double
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define x first
#define y second
using namespace std;
const int N = 2e5 + 10, M = 1010, S = 25;
typedef pair<int, int> pii;
const db eps = 1e-8;
const db pi = acos(-1);
int f[N], n, m;
inline void solve() {
int ans = 50 * 49 / 2 - 7 * 6 / 2;
cout << ans << '\n';
//1204
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cout << fixed << setprecision(8);
// cin >> _;
while(_ --) {
solve();
} return _ ^ _;
}

答案:1204

试题 B: 小球反弹

本题总分:5

思路:由题意,小球返回原点时,在长和宽两个方向所经历的路程均为长方形的长和宽的偶数倍,推公式 (拒绝玄学,开始推公式),设小球返回原点经历的 xy 分量的路程分别为 SxSy ,速度分别为 dxdy ,每次返回原点经历 kx 个矩形长,ky 个矩形宽,所用时间为 t ,有:

{Sx=2kxx=tdxSy=2kyy=tdykxky=dxxdyy

得到的 kxky 为小球每次返回原点时经历的矩形的长和宽的偶数倍,小球第一次返回原点所经历的矩形长和宽倍数为:

{kx1=kxgcd(kx,ky)ky1=kygcd(kx,ky)

于是有小球每次返回原点,经历两分量的路程及时间:

{xn=kx1xnyn=ky1ym(n=0,1,2,3,4...)

所经历的总时间及总路程:

{tn=2kx1xndx=2ky1ymdySn=tdxdx+dydy(n=0,1,2,3,4...)

x=343720y=233333dx=15dy=17 代入,即可求出答案1100325199.77

小球反弹
#include <bits/stdc++.h>
#define int long long
#define deb(x) cout << #x << " = " << x << '\n'
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define all1(f) f.begin() + 1, f.end()
#define here system("pause")
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define MOD 998244353
#define mod 1000000007
#define endl "\n"
#define x first
#define y second
using namespace std;
inline void solve() {
int x = 343720, y = 233333, dx = 15, dy = 17;
int kx = dx * y, ky = dy * x;
int gcd = __gcd(kx, ky);
kx /= gcd, ky /= gcd;
cout << kx << ' ' << ky << '\n';
double t = 2.0 * kx * x / dx;
cout << t << '\n';
double ans = t * sqrt(dx * dx + dy * dy);
cout << ans << '\n';
// 1100325199.77
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
// cin >> _;
cout << fixed << setprecision(2);
while(_ --) {
solve();
}
return _ ^ _;
}

答案:1100325199.77

试题 C: 好数

时间限制: 1.0s 内存限制: 256.0MB 本题总分:10

思路:暴力枚举 1>n ,把当前数转为字符串,判断j % 2 == s[s.size() - j - 1] % 2,若成立则不是好数,统计答案

好数
#include <bits/stdc++.h>
#define int long long
#define db long double
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define x first
#define y second
using namespace std;
const int N = 2e5 + 10, M = 1010, S = 25;
typedef pair<int, int> pii;
const db eps = 1e-8;
const db pi = acos(-1);
int ans, n, m;
inline void solve() {
cin >> n;
for(int i = 1; i <= n; i ++) {
string s = to_string(i);
bool ok = true;
for(int j = 0; j < s.size(); j ++) {
if(j % 2 == s[s.size() - j - 1] % 2) {
ok = false;
break;
}
} if(ok) {
ans ++;
}
} cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cout << fixed << setprecision(2);
// cin >> _;
while(_ --) {
solve();
} return _ ^ _;
}

试题 D: R 格式

时间限制: 1.0s 内存限制: 256.0MB 本题总分:10

思路:用long double存储答案,先乘以 2 的次方倍,在%.0lf浮点数默认向最近的整数格式化输出

R 格式
#include <bits/stdc++.h>
#define int long long
#define db long double
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define x first
#define y second
using namespace std;
const int N = 2e5 + 10, M = 1010, S = 25;
typedef pair<int, int> pii;
const db eps = 1e-8;
const db pi = acos(-1);
db ans, n;
int m;
inline void solve() {
cin >> m >> n;
for(int i = 0; i < m; i ++) {
n *= 2.0;
} cout << n << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cout << fixed << setprecision(0);
// cin >> _;
while(_ --) {
solve();
} return _ ^ _;
}
R 格式(正解高精度)
#include <bits/stdc++.h>
#define int long long
#define db long double
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define x first
#define y second
using namespace std;
const int N = 30, M = 1010, S = 25;
typedef pair<int, int> pii;
const db eps = 1e-8;
const db pi = acos(-1);
inline string add(string a, string b) {
int f = 0;
string ans = "";
if(b == "1") {
for(int i = 1; i < a.size(); i ++) {
b.push_back('0');
} reverse(all(b));
} for(int i = a.size() - 1; i >= 0; i --) {
int v = a[i] - '0' + b[i] - '0' + f;
if(v > 9) {
v %= 10, f = 1;
} else {
f = 0;
} ans.push_back(v + '0');
} if(f) {
ans.push_back('1');
} reverse(all(ans));
return ans;
}
void solve() {
int n, pos = 0;
string s;
cin >> n >> s;
string x = "";
for(int i = 0; i < s.size(); i ++) {
if(s[i] == '.') {
pos = s.size() - i - 1;
break;
}
} for(auto t : s) {
if(t != '.') {
x.push_back(t);
}
} for(int i = 1; i <= n; i ++) {
x = add(x, x);
} char check = x[x.size() - pos];
string xx = "";
for(int i = 0; i < x.size() - pos; i ++) {
xx.push_back(x[i]);
} if(check >= '5') {
xx = add(xx, "1");
}
cout << xx << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cout << fixed << setprecision(0);
// cin >> _;
while(_ --) {
solve();
} return _ ^ _;
}

试题 E: 宝石组合

时间限制: 1.0s 内存限制: 256.0MB 本题总分:15

思路:公式化简后即为求 a,b,c 的最大公约数 gcd(a,b,c,(赛时没化简出来 QWQ ,写了个排序 + 暴力枚举)

宝石组合(暴力)
#include <bits/stdc++.h>
#define int long long
#define db long double
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define x first
#define y second
using namespace std;
const int N = 2e5 + 10, M = 1010, S = 25;
typedef pair<int, int> pii;
const db eps = 1e-8;
const db pi = acos(-1);
int n, m, ans;
int aa, bb, cc;
inline int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
inline int lcm(int a, int b) {
return a * b / gcd(a, b);
}
inline void solve() {
cin >> n;
vector<int> f(n);
for(int i = 0; i < n; i ++) {
cin >> f[i];
} sort(all(f));
for(int i = 0; i < n - 2; i ++) {
for(int j = i + 1; j < n - 1; j ++) {
for(int k = j + 1; k < n; k ++) {
int a = f[i], b = f[j], c = f[k];
int s = a * b * c;
int abc = lcm(lcm(a, b), c);
int ab = lcm(a, b);
int bc = lcm(b, c);
int ac = lcm(a, c);
if(ab > bc) {
swap(ab, bc);
} if(bc > ac) {
swap(bc, ac);
} s = s / ac * abc / ab / bc;
if(s > ans) {
ans = s;
aa = a, bb = b, cc = c;
}
}
}
} cout << aa << ' ' << bb << ' ' << cc << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cout << fixed << setprecision(0);
// cin >> _;
while(_ --) {
solve();
} return _ ^ _;
}
宝石组合(正解)
#include <bits/stdc++.h>
#define int long long
#define db long double
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define x first
#define y second
using namespace std;
const int N = 2e5 + 10, M = 1010, S = 25;
typedef pair<int, int> pii;
const db eps = 1e-8;
const db pi = acos(-1);
int f[N];
int n, p, q, ans, mx;
inline void solve() {
cin >> n;
vector<int> f(n), ans;
map<int, int> mp;
for(int i = 0; i < n; i ++) {
cin >> f[i];
} sort(all(f));
for(int i = 0; i < n; i ++) {
int t = f[i];
for(int j = 1; j <= t / j; j ++) {
if(t % j == 0) {
mp[j] ++;
if(mp[j] >= 3) {
mx = max(mx, j);
} if(t / j != j) {
mp[t / j] ++;
if(mp[t / j] >= 3) {
mx = max(mx, t / j);
}
}
}
}
} for(int i = 0; i < n; i ++) {
if(f[i] % mx == 0) {
ans.emplace_back(f[i]);
}
} cout << ans[0] << ' ' << ans[1] << ' ' << ans[2] << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cout << fixed << setprecision(2);
// cin >> _;
while(_ --) {
solve();
} return _ ^ _;
}

试题 F: 数字接龙

时间限制: 1.0s 内存限制: 256.0MB 本题总分:15

思路:DFS + 剪枝,把方向坐标与数字 1>8 对应初始化,每次递归判断下一个点是否可达 + 是否满足取模后升序 + 是否交叉,后执行递归,递归时传入下一个能到达的点的坐标(x, y) + 当前走的数字a[nx][ny] + 统计的答案tt,若到达右下角x == n - 1&&y == n - 1,则判断并更新答案,答案依旧用long double存,特判答案为-1的情况,按照这个思路,代码调麻了,特殊情况没有特判完,应该不会全对

数字接龙
#include <bits/stdc++.h>
#define int long long
#define deb(x) cout << #x << " = " << x << '\n'
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define all1(f) f.begin() + 1, f.end()
#define here system("pause")
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define MOD 998244353
#define mod 1000000007
#define endl "\n"
#define x first
#define y second
#ifdef LOCAL
#include "algo/debug.h"
#else
#define dbg(...) "cyh2.2"
#define debug(...) "cyh2.2"
#endif
using namespace std;
template <class T> inline void read(T& x) {x = 0;char c = getchar();bool f = 0;for(; !isdigit(c); c = getchar()) f ^= (c == '-'); for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + (c ^ 48); x = f ? -x : x; }
template <class T> inline void write(T x) {if(x < 0) putchar('-'), x = -x;if(x < 10) putchar(x + 48);else write(x / 10), putchar(x % 10 + 48); }
inline int qmi(int a, int b, int p) {int ans = 1 % p;while(b){if(b & 1) ans = ans * a % p;a = a * a % p;b >>= 1;} return ans;}
inline int inv(int a, int p) {return qmi(a, p - 2, p) % p;}
const int N = 2e5 + 10, M = 150, maxn = 20;
const double pi = acos(-1);
const long double E = exp(1);
const double eps = 1e-8;
typedef pair<int, int> pii;
int a[M][M];
int ne[8][2] = {-1, 0, -1, 1, 0, 1, 1, 1, 1, 0, 1, -1, 0, -1, -1, -1};
int n, m;
double ans;
bool st[M][M];
inline void dfs(int x, int y, int t, double tt) {
if(x == n - 1&&y == n - 1) {
string s = to_string(tt);
int x = 0;
for(int i = 0; i < s.size(); i ++) {
if(s[i] == '.') {
x = i;
}
} if(x == n * n - 1) {
ans = min(ans, tt);
} //cout << tt << ' ';
return;
} for(int i = 0; i < 8; i ++) {
int nx = x + ne[i][0];
int ny = y + ne[i][1];
if(nx >= 0&&nx < n&&ny >= 0&&ny < n&&!st[nx][ny]&&((t == m - 1&&a[nx][ny] == 0)||(t < m - 1&&a[nx][ny] == t + 1))) {
bool ok = true;
if(st[nx][y]&&st[x][ny]) {
ok = false;
} if(ok) {
st[nx][ny] = true;
dfs(nx, ny, a[nx][ny], tt * 10 + i);
st[nx][ny] = false;
}
}
}
}
inline void solve() {
ans = 1e27;
cin >> n >> m;
for(int i = 0; i < n; i ++) {
for(int j = 0; j < n; j ++) {
cin >> a[i][j];
}
} if(a[0][0]) {
cout << -1 << '\n';
return ;
} st[0][0] = true;
dfs(0, 0, 0, 0);
if(ans > 1e26) {
ans = -1;
} cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
// cin >> _;
cout << fixed << setprecision(0);
while(_ --) {
solve();
}
return _ ^ _;
}
数字接龙(正解)
#include <bits/stdc++.h>
#define int long long
#define db long double
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define x first
#define y second
using namespace std;
const int N = 30, M = 1010, S = 25;
typedef pair<int, int> pii;
const db eps = 1e-8;
const db pi = acos(-1);
int n, k;
int qx = 0, qy = 0, zx, zy;
int g[N][N], f[N][N], fx[N][N], bu[N * N];
int dx[8] = {-1, -1, 0, 1, 1, 1, 0, -1};
int dy[8] = {0, 1, 1, 1, 0, -1, -1, -1};
int res = 0;
void otto() {
for (int i = 0; i < n * n - 1; ++i)
cout << bu[i];
}
void dfs(int x, int y, int bus, int zt) {
//已经找到结果了,不找了
if (res == 1)
return;
//坐标正确,步数正确,允许输出
if (x == zx && y == zy && bus == n * n - 1) {
//标记为找到
res = 1;
//调用函数把结果打出来
otto();
return;
}
//循环走方格
if (zt == k - 1)
zt = -1;
//八个方向,顺时针就不用管字典序
for (int i = 0; i < 8; ++i) {
//一个新的点的俩坐标
int vx = x + dx[i];
int vy = y + dy[i];
//标记 错号 出界
if (f[vx][vy] || g[vx][vy] != zt + 1 || x < 0 || y < 0 || x >= n || y >= n)
continue;
//如果会交叉
if (i == 1 && (fx[x][y + 1] == 7 || fx[x - 1][y] == 3))
continue;
if (i == 3 && (fx[x][y + 1] == 5 || fx[x + 1][y] == 1))
continue;
if (i == 5 && (fx[x][y - 1] == 3 || fx[x + 1][y] == 7))
continue;
if (i == 7 && (fx[x][y - 1] == 1 || fx[x - 1][y] == 5))
continue;
//开搜
f[vx][vy] = 1;
fx[x][y] = i;
bu[bus] = i;
dfs(vx, vy, bus + 1, g[vx][vy]);
bu[bus] = -1;
fx[x][y] = -1;
f[vx][vy] = 0;
}
}
inline void solve() {
//初始化一些数据
memset(fx, -1, sizeof fx);
memset(f, 0, sizeof f);
memset(bu, -1, sizeof bu);
//输入
cin >> n >> k;
zx = n - 1, zy = n - 1;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
cin >> g[i][j];
}
}
//起点标成走过
f[qx][qy] = 1;
//我搜搜搜
dfs(qx, qy, 0, 0);
//没找到
if (!res) {
cout << -1 << endl;
}
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cout << fixed << setprecision(0);
// cin >> _;
while(_ --) {
solve();
} return _ ^ _;
}

试题 G: 爬山

时间限制: 1.0s 内存限制: 256.0MB 本题总分:20

思路:优先队列 + 贪心,用大根堆存储山的高度 hi,每次取出队头元素,判断 sqrt(x)x2 的大小,若可以操作则取最小值,若相等则优先用 sqrt(x) ,最后累加答案
有网友说大根堆+贪心容易被 Hack ,后面官方题解也是用的这个思路,没办法,再拭目以待吧

爬山
#include <bits/stdc++.h>
#define int long long
#define db long double
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define x first
#define y second
using namespace std;
const int N = 2e5 + 10, M = 1010, S = 25;
typedef pair<int, int> pii;
const db eps = 1e-8;
const db pi = acos(-1);
int f[N];
int n, p, q, ans;
inline void solve() {
cin >> n >> p >> q;
priority_queue<int, vector<int>, less<int> > qq;
for(int i = 1; i <= n; i ++) {
cin >> f[i];
qq.push(f[i]);
} while(q||p) {
int x = qq.top();
qq.pop();
int t = x, a = x, b = x;
if(p > 0) {
a = sqrt(x);
} if(q > 0) {
b = x / 2;
} if(a <= b&&p > 0) {
t = a;
p --;
} else if(q > 0) {
t = b;
q --;
} qq.push(t);
} while(qq.size()) {
int x = qq.top();
qq.pop();
ans += x;
} cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cout << fixed << setprecision(2);
// cin >> _;
while(_ --) {
solve();
} return _ ^ _;
}

试题 H: 拔河

时间限制: 1.0s 内存限制: 256.0MB 本题总分:20

思路:赛时看数据范围+样例说明后直接前缀和 - 后缀和出结果,但数据不一定保证两组成员人数之和必为 n ,一眼障目了 QWQ ,队友用的是前缀和 + 二维二分暴力,但边界情况得处理好,不然也是容易被Hack

拔河
#include <bits/stdc++.h>
#define int long long
#define db long double
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define x first
#define y second
using namespace std;
const int N = 2e5 + 10, M = 1010, S = 25;
typedef pair<int, int> pii;
const db eps = 1e-8;
const db pi = acos(-1);
int f[N], f1[N], f2[N];
int n, ans;
inline void solve() {
cin >> n, ans = 1e18;
for(int i = 1; i <= n; i ++) {
cin >> f[i];
f1[i] = f1[i - 1] + f[i];
} for(int i = n; i >= 1; i --) {
f2[i] = f2[i + 1] + f[i];
} for(int i = 1; i <= n; i ++) {
ans = min(ans, abs(f2[i] - f1[i - 1]));
} cout << ans << '\n';
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cout << fixed << setprecision(2);
// cin >> _;
while(_ --) {
solve();
} return _ ^ _;
}
拔河(正解)
#include <bits/stdc++.h>
#define int long long
#define db long double
#define all(f) f.begin(), f.end()
#define rall(f) f.rbegin(), f.rend()
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define mod 1000000007
#define MOD 998244353
#define x first
#define y second
using namespace std;
const int N = 30, M = 1010, S = 25;
typedef pair<int, int> pii;
const db eps = 1e-8;
const db pi = acos(-1);
void solve() {
int n;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; i ++ ) {
cin >> a[i];
a[i] += a[i - 1];
} map<int, int> pre;
for (int i = 1; i <= n; i ++ ) {
for (int j = i; j <= n; j ++ ) {
pre[a[j] - a[i - 1]] += 1;
}
} int ans = 1E18;
for (int i = n; i >= 2; i -- ) {
for (int j = 1; j <= i; j ++ ) {
int v = a[i] - a[j - 1];
pre[v] --;
if (pre[v] == 0) {
pre.erase(v);
}
} for (int j = i; j <= n; j ++ ) {
int v = a[j] - a[i - 1];
auto t = pre.lower_bound(v);
if (t != pre.end()) {
ans = min(ans, t->first - v);
} t = pre.upper_bound(v);
if (t != pre.begin()) {
--t;
ans = min(ans, v - t->first);
}
}
}
cout << ans << "\n";
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int _ = 1;
cout << fixed << setprecision(0);
// cin >> _;
while(_ --) {
solve();
} return _ ^ _;
}

本文作者:chfychin

本文链接:https://www.cnblogs.com/chfychin/p/18133301

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   chfychin  阅读(2078)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起