A. Zhan's Blender

搅拌机一秒最多能搅拌 \(min(x,c)\) 个水果,因此搅拌的总时间为 \(\lceil\frac{n}{min(x,c)}\rceil\)

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <bits/stdc++.h>

#define int long long
#define x first
#define y second
#define endl '\n'

using namespace std;

typedef pair<int, int> PII;

const int N = 200010;

int T;
int n, x, y;

signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);

cin >> T;
while (T--)
{
cin >> n >> x >> y;

int t = min(x, y);
cout << (n + t - 1) / t << endl;
}

return 0;
}

B. Battle for Survive

由于只能由高位战士淘汰低位战士,因此最后剩下的战士一定是第 \(n\) 个战士

为了使第 \(n\) 个战士保留评级最大,就要使 \([1,n-1]\) 中最后剩下的战士评级最小

\([1,n-1]\) 中剩下的战士一定是第 \(n - 1\) 个战士,为了使他保留的评级最小,可以用他来淘汰除 \(n\) 以外的所有战士

最终答案为 \(a[n]-(a[n-1]-\sum_{i}^{n-2}a[i])\)

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <bits/stdc++.h>

#define int long long
#define x first
#define y second
#define endl '\n'

using namespace std;

typedef pair<int, int> PII;

const int N = 200010;

int T;
int n;
int a[N];

signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);

cin >> T;
while (T--)
{
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];

int res = a[n - 1] - a[n - 2];
for (int i = 0; i < n - 2; i++) res += a[i];

cout << res << endl;
}

return 0;
}

C. Password Cracking

交互题

每次询问在已知子串右边再拼接 \(0\) 或者 \(1\),如果获得的回答都是 \(0\),代表目前的字串是密码串的后缀,之后的每次询问在子串左边拼接即可

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <bits/stdc++.h>

#define int long long
#define x first
#define y second

using namespace std;

typedef pair<int, int> PII;

const int N = 200010;

int T;
int n;

signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);

cin >> T;
while (T--)
{
cin >> n;

string s;

bool flag = false;
while (1)
{
if (flag)
{
string t = '1' + s;
cout << "? " << t << endl;
int x;
cin >> x;
if (x) s = '1' + s;
else s = '0' + s;
}
else
{
string t = s + '1';
cout << "? " << t << endl;
int x;
cin >> x;
if (x) s += '1';
else
{
t = s + '0';
cout << "? " << t << endl;
cin >> x;
if (x) s += '0';
else flag = true;
}
}
if (s.size() == n)
{
cout << "! " << s << endl;
break;
}
}
}

return 0;
}

D. Minimize the Difference

首先二分找到该序列能操作出的最大最小值 \(minv\)

接着把序列中的每个元素都处理成大于等于 \(minv\),为了之后的可操作性更强

对于大于 \(minv\) 的部分,应尽量留在下标小的地方

最后对新序列进行二分,找到新序列最小的最大值

code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 200010;

int T;
int n;
ll a[N];

bool check1(ll x)
{
ll cnt = a[0];
for (int i = 0; i < n; i++)
{
if (cnt < x) return false;
cnt += a[i + 1] - x;
}
return true;
}

bool check2(ll x)
{
ll cnt = a[0];
for (int i = 0; i < n; i++)
{
if (cnt > x)
{
if (i == n - 1) return false;
else cnt += a[i + 1] - x;
}
else cnt = a[i + 1];
}
return true;
}

int main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);

cin >> T;
while (T--)
{
cin >> n;
for (ll i = 0; i < n; i++) cin >> a[i];

ll l = 0, r = 1e12;
while (l < r)
{
ll mid = l + r + 1 >> 1;
if (!check1(mid)) r = mid - 1;
else l = mid;
}

for (int i = n - 1; i >= 0; i--)
{
if (a[i] < l) a[i - 1] -= l - a[i], a[i] = 0;
else a[i] -= l;
}

l = 0, r = 1e12;
while (l < r)
{
ll mid = l + r >> 1;
if (!check2(mid)) l = mid + 1;
else r = mid;
}

cout << l << '\n';
}

return 0;
}

E. Prefix GCD

由于 \(gcd\) 每次缩小至少会除以 \(2\),因此,从开始缩减到最小 \(gcd\) 只需要 \(log\)

显然,\(a[0]\) 一定要取数组最小值,接下来每一次取值,都要找剩下元素中能使当前 \(gcd\) 最小的,直到 \(gcd\) 缩小为最小 \(gcd\),跳出循环

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#include <bits/stdc++.h>

#define x first
#define y second

using namespace std;

typedef long long ll;

const int N = 200010;

int T;
int n;
int a[N];

int gcd(int a, int b)
{
return b? gcd(b, a % b) : a;
}

int main()
{
cin >> T;
while (T--)
{
cin >> n;
for (int i = 0; i < n; i++) cin >> a[i];

sort(a, a + n);

int g = 0;
map<int, int> p;
for (int i = 0; i < n; i++)
{
g = gcd(g, a[i]);
if (i) p[i]++;
}

ll res = a[0], cnt = a[0];
while (cnt > g)
{
int d = cnt, id = 0;
for (auto it: p)
{
int t = gcd(d, a[it.x]);
if (cnt > t) cnt = t, id = it.x;
}
res += cnt;
p.erase(id);
}
for (auto it: p) res += cnt;

cout << res << endl;
}

return 0;
}