牛客2021年多校训练营<1>
Alice and Bob
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述 :
Alice and Bob like playing games. There are two piles of stones with numbers {n}n and {m}m. Alice and Bob take turns to operate, each operation can take away {k}(k>0)k(k>0) stones from one pile and take away s \times k(s \geq 0)s×k(s≥0) stones from another pile. Alice plays first. The person who cannot perform the operation loses the game.
Please determine who will win the game if both Alice and Bob play the game optimally.
输入描述:
The first line contains an integer T(1 \le T \le 10^4)T(1≤T≤10
4
) denotes the total number of test cases.
Each test case contains two integers n,m(1 \le n,m \leq 5 \times 10^3)n,m(1≤n,m≤5×10
3
) in a line, indicating the number of two piles of stones.
输出描述:
For each test case, print “Alice” if Alice will win the game, otherwise print “Bob”.
示例1
输入
5
2 3
3 5
5 7
7 5
7 7
输出
Bob
Alice
Bob
Bob
Alice
思路:
SG函数:
从(0,0)开始递推,由于(0,0)是必输态,则一部可达(0,0)的都是必胜态,不断更新sg[m][n]函数,直到m,n=5000为止,此时,只需查询sg函数中值即可。
代码:
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <iomanip>
using namespace std;
typedef long double ld;
typedef long long ll;
const int maxn = 5005;
bool sg[maxn][maxn];
int main() {
for (int i = 0; i < maxn; i++) {
for (int j = 0; j < maxn; j++) {
if (!sg[i][j]) {//后手必赢情况
for (int k = 1; k + i < maxn; k++) {
for (int s = 0; s * k + j < maxn; s++) {
sg[k + i][s * k + j] = 1;
}
}
for (int k = 1; k + j < maxn; k++) {
for (int s = 0; s * k + i < maxn; s++) {
sg[s * k + i][k + j] = 1;
}
}
}
}
}
int t;
cin >> t;
while (t--) {
int m, n;
scanf("%d %d", &n, &m);
if (sg[n][m]) printf("Alice\n");
else printf("Bob\n");
}
return 0;
}
ps.scanf和printf是好东西,cin,cout加了解绑也会爆时间就离谱好吧。。。。。。
Ball Dropping
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld
题目描述
A standard sphere ball is falling in the air, and the center of the sphere is exactly on the centerline of an empty isosceles trapezoidal. The trapezoid is hanging horizontally under the sphere.
Please determine whether the ball will get stuck in the trapezoid or drop past the trapezoid.
输入描述:
The input contains four integers r, a, b, h(1 \le r,a,b,h \le 1000, a > b)r,a,b,h(1≤r,a,b,h≤1000,a>b), indicating the radius of the ball, the top base, the bottom base, and the height of the isosceles trapezoid.
输出描述:
Output ‘Drop’ if the sphere ball will drop past the empty trapezoid, otherwise output ‘Stuck’.
If the answer is ‘Stuck’, please also calculate the stuck position(the height between the center of the sphere and the midpoint of the bottom base). Your answer is considered correct if its absolute or relative error does not exceed 10^−6
思路:
2*r与b相比,大于会卡住,小于落下,卡住时推公式求解
代码
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <iomanip>
using namespace std;
typedef long double ld;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
ld r, a, b, h;
cin >> r >> a >> b >> h;
if (2 * r >= b) {
cout << "Stuck" << endl; ld ll;
ll = h * h + (a - b) * (a - b) / 4;
ll = pow(ll, 0.5);
ld x = (b * h - 2 * ll * r) / (b - a);
cout << fixed << setprecision(9) << x << endl;
}
else {
cout << "Drop" << endl;
}
return 0;
}
Determine the Photo Position
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述 :
You have taken the graduation picture of graduates. The picture could be regarded as a matrix A of n \times nn×n, each element in A is 0 or 1, representing a blank background or a student, respectively.
However, teachers are too busy to take photos with students and only took a group photo themselves. The photo could be regarded as a matrix B of 1 \times m1×m where each element is 2 representing a teacher.
As a master of photoshop, your job is to put photo B into photo A with the following constraints:
you are not allowed to split, rotate or scale the picture, but only translation.
each element in matrix B should overlap with an element in A completely, and each teacher should overlap with a blank background, not shelter from a student.
Please calculate the possible ways that you can put photo B into photo A.
.
输入描述:
The first line contains two integers n,m(1 \le n,m \le 2000)n,m(1≤n,m≤2000) indicating the size of photos A and B.
In the next n n n lines,each line contains {n}n characters of ‘0’ or ‘1’,representing the matrix A.
The last line contains {m}m characters of ‘2’, representing matrix B.
输出描述:
Output one integer in a line, indicating the answer.
思路:就普遍理性而言,维护个前缀和在插一遍就行了
代码
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int n, m;
vector<int> B;
vector<vector<int> > A;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
A.resize(n + 1);
B.resize(m + 1);
for (int i = 0; i <= n; ++i)
{
A[i].resize(n + 1);
}
for (int i = 1; i <= n; ++i)
{
string tmp;
cin >> tmp;
tmp = '0' + tmp;
for (int j = 1; j <= n; ++j)
{
A[i][j] = A[i][j - 1] + tmp[j] - '0';
}
}
string tmp;
cin >> tmp;
int ans = 0;
for (int i = 1; i <= n; ++i)
{
for (int j = m; j <= n; ++j)
{
if (A[i][j] - A[i][j - m] == 0)
{
++ans;
}
}
}
cout << ans << endl;
return 0;
}
Game of Swapping Numbers
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
输入描述:
输出描述:
Output one integer, the maximum answer.
样例:
思路:
赋予同等的±号,使得数组间差的绝对值最大,通过推导可得,最优的解比原解大
根据引理有n>2时,操作k次和操作不超过k次等价,再将那么根据引理,将所有 min数组和max数组分别从小到大、从大到小 sort 一遍,从前往后扫一遍,当后者大于前者时就将贡献加上,这样做能够使贡献最大化。
代码:
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef long double ld;
const int N = 500005;
ll a[N];
ll b[N];
ll mi[N];
ll ma[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int n, k;
ll sum = 0;
cin >> n >> k;
if (n == 2) {
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i < n; i++) {
cin >> b[i];
}
if (k & 1)swap(a[0], a[1]);
sum = abs(a[0] - b[0]) + abs(a[1]- b[1]);
cout << sum;
return 0;
}
for (int i = 0; i < n; i++) {
cin >> a[i];
}
for (int i = 0; i < n; i++) {
cin >> b[i];
}
for (int i = 0; i < n; i++) {
sum = sum + abs(a[i] - b[i]);
}
for (int i = 0; i < n; i++) {
mi[i] = min(a[i], b[i]);
ma[i] = max(a[i], b[i]);
}
sort(mi, mi + n);
sort(ma, ma + n);
for (int i = 0; i < n && i < k; i++) {
if (mi[n - i - 1] > ma[i]) {
sum += 2 * (mi[n - i - 1] - ma[i]);
}
else {
break;
}
}
cout << sum << endl;
return 0;
}
Escape along Water Pipe
时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 524288K,其他语言1048576K
Special Judge, 64bit IO Format: %lld
题目描述:
You’re trapped into a map with n \times mn×m grids, each grid has a strange water pipe.
There are six types of water pipes, denote them as ID 0,1,\dots,50,1,…,5.
You are located at the top of grid {(1,1)}(1,1) and you want to reach the bottom of grid {(n,m)}(n,m). In each step, you should travel along the pipe and move to another grid.
Before each move, you can do beautiful magic once: pick one of the degrees from {{0, 90, 180, 270}}{0,90,180,270}, select any number of grids except the one you are located at, and rotate their water pipes with the same degree you pick in the clockwise direction. Note that after you step in a grid along the water pipe, you must walk along the other end of the pipe to leave this grid.
You may step in the same grid multiple times, and the direction can be different every time you enter.
Determine whether you can escape from the entrance to the exit successfully.
输入描述:
输出描述:
思路:
不会,先存着。