牛客小白月赛33
A-字符统计
题意
给定一段字符,统计行数、单词数和字符数。
方法
用getline()读取每一行字符串即可。
C++代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int T;
cin >> T;
cin.get();
while (T--) {
string s;
int lines = 0, words = 0, ch = 0;
while (getline(cin, s) && s != "=====") {
lines++;
ch += s.size();
for (int i = 0; i < (int) s.size(); ++i) {
if (s[i] != ' ') {
words++;
while (i < (int) s.size() && s[i] != ' ') i++;
}
}
}
cout << lines << ' ' << words << ' ' << ch << '\n';
}
return 0;
}
D-购物
题意
给定\(S\)种商品和每种商品的数量,已知\(N\)个人所拥有的商品,每个人都要凑齐所有商品种类,问剩余的商品种类数。
方法
按题意模拟即可。
C++代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int n, m;
cin >> n >> m;
map<string, int> cnt;
while (n--) {
string s;
cin >> s;
int t;
cin >> t;
cnt[s] = t;
}
while (m--) {
int k;
cin >> k;
set<string> has;
while (k--) {
string s;
cin >> s;
has.insert(s);
}
for (auto& [u, v] : cnt) {
if (has.find(u) == has.end()) {
v--;
}
}
}
int ans = 0;
for (auto& [u, v] : cnt) {
if (v > 0) ans++;
}
if (ans == 0) {
cout << "Need to be lucky\n";
} else {
cout << ans << '\n';
}
}
return 0;
}
B-连分数
题意
给定一个分数,问能否写成连分数的形式。
示例
输入
3
103 24
21 73
4 2
输出
103/24 = 4+1/{3+1/{2+1/3}}
21/73 = 0+1/{3+1/{2+1/10}}
4/2 = 2
方法
观察可得,每个分数都可以写成商加上一个分子为1的分数的形式,递归计算即可。
C++代码
#include <bits/stdc++.h>
using namespace std;
void recur(int so, int mo, int& le) {
cout << so / mo;
if (so % mo) {
cout << "+1/";
so %= mo;
if (mo % so) {
cout << "{";
le++;
}
recur(mo, so, le);
}
}
int main() {
int T;
cin >> T;
while (T--) {
int so, mo;
cin >> so >> mo;
cout << so << "/" << mo << " = ";
int le = 0;
recur(so, mo, le);
while (le--) {
cout << "}";
}
cout << '\n';
}
return 0;
}
E-喝可乐
题意
给定两种可乐,价钱相同,其中\(A\)个第1种可乐的空瓶子可以兑换\(1\)瓶第2种可乐,\(B\)个第2种可乐的空瓶子可以兑换\(1\)瓶第1种可乐。已知身上的钱只能买\(n\)瓶可乐,问可以喝到的可乐的最大数量。
方法
按题意模拟即可。
C++代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int n, a, b;
cin >> n >> a >> b;
int ans = 0;
for (int i = 0; i <= n; ++i) {
int c1 = i, c2 = n - i, res = c1 + c2;
while (c1 >= a || c2 >= b) {
if (c1 >= a) {
c2 += c1 / a;
res += c1 / a;
c1 %= a;
}
if (c2 >= b) {
c1 += c2 / b;
res += c2 / b;
c2 %= b;
}
}
ans = max(ans, res);
}
cout << ans << '\n';
}
return 0;
}
F-天旋地转
题意
在二维平面上给定\(6\)种操作,分别是将坐标系顺时针旋转90°、逆时针旋转90°,向前、向后、向左、向右走\(k\)个单位。已知初始位置和面向方向,问最终的位置。
方法
按题意模拟即可。
C++代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void change(int d, char s, int k, ll& x, ll& y) {
if (d == 0) {
if (s == 'w') y += k;
else if (s == 's') y -= k;
else if (s == 'd') x += k;
else x -= k;
} else if (d == 1) {
if (s == 'w') x -= k;
else if (s == 's') x += k;
else if (s == 'd') y += k;
else y -= k;
} else if (d == 2) {
if (s == 'w') y -= k;
else if (s == 's') y += k;
else if (s == 'd') x -= k;
else x += k;
} else {
if (s == 'w') x += k;
else if (s == 's') x -= k;
else if (s == 'd') y -= k;
else y += k;
}
}
int main() {
int T;
cin >> T;
while (T--) {
int q;
cin >> q;
ll x = 0, y = 0;
int d = 0;
while (q--) {
char s;
int k;
cin >> s >> k;
if (s == 'r') {
d = (d + k) % 4;
} else if (s == 'l') {
d = (d - k + (k / 4 + 1) * 4) % 4;
} else {
change(d, s, k, x, y);
}
}
cout << x << ' ' << y << '\n';
}
return 0;
}
I-三角尼姆
题意
给定一个边长为\(n\)的正三角形棋盘,每次可以摆放一枚或三枚棋子且保证所放棋子成直线。已知两个人先后下棋,最后一个放下棋子的人是输家,问是哪位。
方法
假设棋盘总空位数为奇数,则先手无论怎么下,后手都可以让先手面对的棋盘剩余空位数始终保持为奇数,此时先手必输。偶数同理。
C++代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
int sum = 0;
for (int i = 1; i <= n; ++i) sum += i;
if (sum & 1) cout << "Alice\n";
else cout << "Bob\n";
}
return 0;
}
J-线段的交
题意
给定两条线段的四个端点,如果两线段相交则求出四点围成的四边形面积,保证不存在某条线段的端点在另一条线段上。
方法
根据向量积判断两线段是否相交,然后取其中三个点逆时针排序从而根据公式计算三角形的面积,四边形的面积是其两倍。
C++代码
#include <bits/stdc++.h>
using namespace std;
struct Point {
double x, y;
Point() {}
Point(double x, double y) : x(x), y(y) {}
bool operator<(const Point& r) const {
return x < r.x;
}
};
// 计算叉积
double get_mul(Point p1, Point p2, Point p0) {
double x1 = p1.x - p0.x, x2 = p2.x - p0.x;
double y1 = p1.y - p0.y, y2 = p2.y - p0.y;
return x1 * y2 - x2 * y1;
}
bool check_cross(Point p1, Point p2, Point p3, Point p4) {
bool ok = get_mul(p2, p3, p1) * get_mul(p2, p4, p1) < 0;
if (ok) {
ok = get_mul(p1, p4, p3) * get_mul(p2, p4, p3) < 0;
}
return ok;
}
double get_dis(Point p1, Point p2) {
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
double get_tri_area(Point p1, Point p2, Point p3) {
double t1 = p1.x * p2.y + p2.x * p3.y + p3.x * p1.y;
double t2 = p1.x * p3.y + p2.x * p1.y + p3.x * p2.y;
return 1. / 2 * (p1.x * p2.y + p2.x * p3.y + p3.x * p1.y - p1.x * p3.y - p2.x * p1.y - p3.x * p2.y);
}
int main() {
Point p1, p2, p3, p4;
cin >> p1.x >> p1.y >> p2.x >> p2.y >> p3.x >> p3.y >> p4.x >> p4.y;
if (check_cross(p1, p2, p3, p4)) {
double ans = 0;
// p1, p2, p3必须逆时针排列
if (get_mul(p3, p2, p1) < 0) {
ans = get_tri_area(p1, p2, p3) + get_tri_area(p1, p4, p2);
} else {
ans = get_tri_area(p1, p3, p2) + get_tri_area(p1, p2, p4);
}
cout << setprecision(8) << ans << '\n';
} else {
cout << 0 << '\n';
}
return 0;
}
G-切圈圈
题意
给定一个环形数组且数组和为0,问最多可以将数组切割成多少个片段。
方法
求前缀和,若两前缀和相等,则说明两点间的数组和为0,可以切割。
C++代码
#include <bits/stdc++.h>
using namespace std;
int main() {
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<int> a(n);
for (int& x : a) cin >> x;
vector<int> pre(n);
map<int, vector<int>> mp;
vector<int> res(n);
for (int i = 0; i < n; ++i) {
if (i == 0) pre[i] = a[i];
else pre[i] = pre[i - 1] + a[i];
if (mp.count(pre[i])) {
int j = mp[pre[i]].back();
res[i] = res[j] + 1;
} else {
res[i] = 0;
}
mp[pre[i]].emplace_back(i);
}
int ans = 1;
for (int i = 0; i < n; ++i) ans = max(ans, res[i] + 1);
cout << ans << '\n';
}
return 0;
}
H-货物运输
题意
给定\(n\)座城市,任务是将\(f\)箱货物从\(st\)城市运送到\(ed\)城市。有\(m\)种从一个城市运送货物到另一个城市的方案,每个方案\(P_i\)按\(C_i\)每箱的价格将\(D_i\)箱货物从\(A_i\)运到\(B_i\),如果货物数量大于\(D_i\),则多出来的每箱按\(C_i'\)的价格运送。问最小的花费。
方法
简单的单源汇最短路问题,\(dijkstra\)或\(spfa\)算法均可。
C++代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 110, M = 10010;
int h[N], e[M], ne[M], idx;
ll w[M];
int n, m, st, ed, f;
int a, b, c1, d, c2;
ll dist[N];
bool vis[N];
void add(int a, int b, ll c) {
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}
ll spfa() {
memset(dist, 0x7f, sizeof dist);
memset(vis, false, sizeof vis);
dist[st] = 0;
queue<int> que;
que.push(st);
vis[st] = true;
while (!que.empty()) {
int u = que.front();
que.pop();
vis[u] = false;
for (int i = h[u]; ~i; i = ne[i]) {
int v = e[i];
if (dist[v] > dist[u] + w[i]) {
dist[v] = dist[u] + w[i];
if (!vis[v]) {
que.push(v);
vis[v] = true;
}
}
}
}
return dist[ed];
}
int main() {
int T;
cin >> T;
while (T--) {
memset(h, -1, sizeof h);
idx = 0;
cin >> n >> m >> st >> ed >> f;
while (m--) {
cin >> a >> b >> c1 >> d >> c2;
ll w = 1LL * c1 * min(f, d) + 1LL * c2 * max(0, f - d);
add(a, b, w);
}
cout << spfa() << '\n';
}
return 0;
}

浙公网安备 33010602011771号