2021 牛客多校2 题解
C Draw Grids
n个点,两个点之间连一条线,不成环,很明显只能连n*m-1条边
此时判断先手胜负非常简单了
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
if (n > m) swap(n, m);
if ((m * n - 1) & 1)
puts("YES");
else
puts("NO");
return 0;
} D Er Ba Game
按题意模拟即可
#include <bits/stdc++.h>
using namespace std;
void solve() {
int a, b, c, d;
cin >> a >> b >> c >> d;
if (a > b)
swap(a, b);
if (c > d)
swap(c, d);
if (a == 2 and b == 8) {
if (c == 2 and d == 8)
cout << "tie" << endl;
else
cout << "first" << endl;
} else if (c == 2 and d == 8)
if (a == 2 and b == 8)
cout << "tie" << endl;
else
cout << "second" << endl;
else if (a == b) {
if (c == d) {
if (a > c)
cout << "first" << endl;
else if (c > a)
cout << "second" << endl;
else
cout << "tie" << endl;
} else
cout << "first" << endl;
} else if (c == d)
cout << "second" << endl;
else if ((a + b) % 10 > (c + d) % 10)
cout << "first" << endl;
else if ((a + b) % 10 < (c + d) % 10)
cout << "second" << endl;
else if (b == d)
cout << "tie" << endl;
else if (b > d)
cout << "first" << endl;
else
cout << "second" << endl;
}
signed main() {
int t;
cin >> t;
while (t--)
solve();
return 0;
} F Girlfriend
题意
给定空间中四个点 ,求点
满足
的所有点集。
可以很明显的发现 和
的所有点集为一个球,问题即可转化为求两个球的交集
分类讨论两个球之间相交、相离、内切等情况即可求出
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long double ld;
typedef long long ll;
const ld pi = acos(-1);
const ld eps = 1e-8;
struct point {
ld x, y, z;
point operator+(const point &a) {
point t;
t.x = x + a.x, t.y = y + a.y, t.z = z + a.z;
return t;
}
point operator/(const ld k) {
point t;
t.x = x / k, t.y /= k, t.z /= k;
return t;
}
ld sd() { return x * x + y * y + z * z; }
};
struct ball {
point center;
ld rad;
};
ld getdis(point a, point b) {
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) +
(a.z - b.z) * (a.z - b.z));
}
ld getV(ball a) { return 4.0 * pi * a.rad * a.rad * a.rad / 3.0; }
ld getcos(ld a, ld b, ld c) { return (a * a + b * b - c * c) / (2 * a * b); }
ld getVs(ld h, ld r) { return pi / 3.0 * (3.0 * r - h) * h * h; }
ld cal(ball a, ball b) {
ld dis = getdis(a.center, b.center);
if (dis >= (a.rad + b.rad))
return 0;
else if (dis + a.rad - b.rad < eps)
return getV(a);
else if (dis + b.rad - a.rad < eps)
return getV(b);
else {
ld alpha = getcos(a.rad, dis, b.rad), beta = getcos(dis, b.rad, a.rad);
ld h1 = a.rad * (1 - alpha), h2 = b.rad * (1 - beta);
return getVs(h1, a.rad) + getVs(h2, b.rad);
}
}
ball getcenter(ld k, point a, point b) {
ld A, B, C, D, tmp;
k = k * k, tmp = 1 - k;
A = 2 * (k * b.x - a.x) / tmp;
B = 2 * (k * b.y - a.y) / tmp;
C = 2 * (k * b.z - a.z) / tmp;
D = -(k * b.sd() - a.sd()) / tmp;
ball res;
res.center.x = A / 2, res.center.y = B / 2, res.center.z = C / 2;
res.rad = sqrt((A * A + B * B + C * C - D * 4.0) / 4.0);
return res;
}
void solve() {
point A, B, C, D;
ld k1, k2;
cin >> A.x >> A.y >> A.z >> B.x >> B.y >> B.z >> C.x >> C.y >> C.z >> D.x >>
D.y >> D.z >> k1 >> k2;
ball a, b;
a = getcenter(k1, A, B);
b = getcenter(k2, C, D);
cout << cal(a, b) << endl;
}
signed main() {
int t;
cin >> t;
while (t--)
solve();
return 0;
} I Penguins
题意
左右各有两只企鹅,需要操作左边的企鹅,右边的企鹅会随着左边的运动而对应的镜像运动
即:左边 向上、下、左、右
右边 向上、下、右、左
使得左边的企鹅从右下角移动到右上角,右边的企鹅从左下角移动到左上角
输出字典序最小的操作方式
按照字典序按顺序模拟操作即可
#include <bits/stdc++.h>
using namespace std;
#define rep(i, l, r) for (int i = l; i <= r; ++i)
const int N = 50;
char a[N][N], b[N][N], go[] = "DLRU";
bool vis[N][N][N][N];
int dis[4][4] = {{1, 0, 1, 0}, {0, -1, 0, 1}, {0, 1, 0, -1}, {-1, 0, -1, 0}};
inline bool chk(int x, int y, char a[][N]) {
if (x > 20 || x <= 0 || y > 20 || y <= 0 || a[x][y] == '#')
return 1;
else
return 0;
}
struct node {
int ax, ay, bx, by;
string s = "";
};
string bfs() {
queue<node> q;
node st = {20, 20, 20, 1, ""}, now, tmp;
q.push(st);
vis[st.ax][st.ay][st.bx][st.by] = 1;
while (!q.empty()) {
now = q.front();
q.pop();
if (now.ax == 1 and now.ay == 20 and now.bx == 1 and now.by == 1)
return now.s;
rep(i, 0, 3) {
int ax = now.ax + dis[i][0], ay = now.ay + dis[i][1],
bx = now.bx + dis[i][2], by = now.by + dis[i][3];
if (chk(ax, ay, a))
ax -= dis[i][0], ay -= dis[i][1];
if (chk(bx, by, b))
bx -= dis[i][2], by -= dis[i][3];
if (!vis[ax][ay][bx][by]) {
vis[ax][ay][bx][by] = 1;
q.push({ax, ay, bx, by, now.s + go[i]});
}
}
}
return "";
}
signed main() {
rep(i, 1, 20) scanf("%s", a[i] + 1), scanf("%s", b[i] + 1);
string s = bfs();
cout << s.size() << endl << s << endl;
int ax = 20, ay = 20, bx = 20, by = 1;
for (char c : s) {
a[ax][ay] = 'A', b[bx][by] = 'A';
if (c == 'D') {
ax += dis[0][0], ay += dis[0][1], bx += dis[0][2], by += dis[0][3];
if (chk(ax, ay, a))
ax -= dis[0][0], ay -= dis[0][1];
if (chk(bx, by, b))
bx -= dis[0][2], by -= dis[0][3];
}
if (c == 'L') {
ax += dis[1][0], ay += dis[1][1], bx += dis[1][2], by += dis[1][3];
if (chk(ax, ay, a))
ax -= dis[1][0], ay -= dis[1][1];
if (chk(bx, by, b))
bx -= dis[1][2], by -= dis[1][3];
}
if (c == 'R') {
ax += dis[2][0], ay += dis[2][1], bx += dis[2][2], by += dis[2][3];
if (chk(ax, ay, a))
ax -= dis[2][0], ay -= dis[2][1];
if (chk(bx, by, b))
bx -= dis[2][2], by -= dis[2][3];
}
if (c == 'U') {
ax += dis[3][0], ay += dis[3][1], bx += dis[3][2], by += dis[3][3];
if (chk(ax, ay, a))
ax -= dis[3][0], ay -= dis[3][1];
if (chk(bx, by, b))
bx -= dis[3][2], by -= dis[3][3];
}
}
a[1][20] = b[1][1] = 'A';
rep(i, 1, 20) printf("%s %s\n", a[i] + 1, b[i] + 1);
return 0;
} K Stack
题意
给出一个排列 通过下面伪码构造一个序列
Stk is an empty stack
for i = 1 to n :
while ( Stk is not empty ) and ( Stk's top > a[i] ) :
pop Stk
push a[i]
b[i]=Stk's size 先给定 中
个元素,构造排列
明显发现:序列 存储的是当
中第
个元素进栈时栈中满足栈顶元素比它小的栈的元素个数(单调栈
考虑每个元素都是大于上一个元素,即全都压栈,计算出每个元素压栈时栈的元素数量,然后在从后往前,模拟压栈顺序,依次取出即可。
#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (ll(i) = (j); (i) <= (k); (++i))
#define rrep(i, j, k) for (ll i = (ll)(j); i >= (ll)(k); i--)
typedef long long ll;
const int N = 1e6 + 7;
ll a[N], b[N], st[N];
signed main() {
int n, k, t, cnt = 0;
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> k;
rep(i, 1, k) cin >> t >> a[t];
rep(i, 1, n) {
if (!a[i]) // 当前元素压栈
a[i] = a[i - 1] + 1;
else if (a[i] > a[i - 1] + 1) // 当前元素压栈,栈中元素数量只会多1,否则不行
return cout << "-1\n", 0;
}
st[t = 0] = 0;
// 从后往前模拟加入的元素即可
rrep(i, n, 1) {
while (a[i] > t)
st[++t] = ++cnt;
b[i] = st[t--];
}
rep(i, 1, n) cout << b[i] << " \n"[i==n];
return 0;
}
顺丰集团工作强度 307人发布