0%

2023牛客暑期多校2(D E F G H I K)

题目链接

由易到难为:IE,KFD,HG

I. Link with Gomoku

仿照样例构造即可

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
77
78
79
#include <bits/stdc++.h>
using namespace std;
int t;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin >> t;
while(t--)
{
int n,m;
cin >> n >> m;
if(n == 1 && m == 1)
{
cout << 'x' << '\n';
}else
{
if(n & 1)
{
char temp = 'x';
for(int i = 1;i < n;++i)
{
if(i & 1)
{
temp = 'x';
}else
{
temp = 'o';
}
for(int j = 1;j <= m;++j)
{
if(j % 4 == 1)
{
if(temp == 'x')
temp = 'o';
else
temp = 'x';
}
cout << temp;
}
cout << '\n';
}
for(int i = 1;i <= m;++i)
{
if(i & 1)
cout << 'x';
else
cout << 'o';
}
cout << '\n';
}else
{
char temp = 'x';
for(int i = 1;i <= n;++i)
{
if(i & 1)
{
temp = 'x';
}else
{
temp = 'o';
}
for(int j = 1;j <= m;++j)
{
if(j % 4 == 1)
{
if(temp == 'x')
temp = 'o';
else
temp = 'x';
}
cout << temp;
}
cout << '\n';
}
}
}
}
}

E. Square

由于数据范围的限制,可以对 枚举所有可能的 ,之后暴力查看对于给定的 是否有满足条件的 即可

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>
using namespace std;
int t;
typedef long long ll;
ll x;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin >> t;
while(t--)
{
cin >> x;
ll ans = -1,l = 10;
for(int i = 1;i <= 9 && ans == -1;++i)
{
if(i != 1)
{
l *= 10;
}
ll cur_ans = sqrt(x * l);
if(((cur_ans * cur_ans) / l < x) && (cur_ans + 1) * (cur_ans + 1) / l == x)
{
ans = cur_ans + 1;
}else if(cur_ans * cur_ans / l == x)
{
ans = cur_ans;
}
}
cout << ans << endl;
}
}

K. Box

线性dp, 分别表示 前移, 不移动, 后移的最大值,对于最初没有 的地方分类讨论即可。

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
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
ll dp[N][3];
ll a[N],b[N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int n;
cin >> n;
for(int i = 1;i <= n;++i)
{
cin >> a[i];
}
for(int i = 1;i <= n;++i)
{
cin >> b[i];
}
dp[0][0] = 0,dp[0][1] = -1e18,dp[0][2] = -1e18;
for(int i = 1;i <= n;++i)
{
if(b[i])
{
dp[i][0] = a[i - 1] + dp[i - 1][0];
dp[i][1] = a[i] + max(dp[i - 1][0],dp[i - 1][1]);
dp[i][2] = a[i + 1] + max(max(dp[i - 1][0],dp[i - 1][1]),dp[i - 1][2]);
}else
{
dp[i][0] = max(dp[i - 1][1],dp[i - 1][0]);
dp[i][1] = dp[i - 1][2];
dp[i][2] = -1e18;
}
}
cout << max(dp[n][0],dp[n][1]) << endl;
}

F. Link with Chess Game

本题可看作在一个 的立方体内,从 开始移动,每次只能移动一格距离,最先到达先前到达过状态的人输,由于每次只能移动距离一,因此每次移动都会改变 中任意一维的奇偶性于是可以转化成类似二分图最大匹配的问题,当 为偶数时,所有点都位于最大匹配上,先手必胜;当 为奇数时,数量较少的一部分位于最大匹配,数量较多的另一部分去掉一个点后最大匹配不变,此时若 位于数量较多的部分则先手必输,否则先手必胜,

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
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int t;
cin >> t;
while(t--)
{
int n,r,g,b;
cin >> n >> r >> g >> b;
if(n % 2 == 0)
{
cout << "Alice\n";
}else
{
if((r + g + b) % 2 == 1)
{
cout << "Bob\n";
}else
{
cout << "Alice\n";
}
}
}
}

D. The Game of Eating

贪心题,假设当前是最后一个人,那么他一定会在剩下的所有菜中挑自己最爱吃的,那么前一个人为了不浪费,应该在除去这道菜的菜里选自己最爱吃的,以此类推,每次拿当前人最喜欢的菜,然后将这道菜对所有人的权重置0,从 模拟一遍即可

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
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[2010][2010];
bool cmp(ll x,ll y)
{
return x > y;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int t;
cin >> t;
while(t--)
{
int n,m,k;
cin >> n >> m >> k;
for(int i = 1;i <= n;++i)
{
for(int j = 1;j <= m;++j)
{
cin >> a[i][j];
}
}
vector<int>ans;
for(;k >= 1;--k)
{
int cur = k % n;
if(!cur)
cur = n;
int mx = 0,pos = 0;
for(int j = 1;j <= m;++j)
{
if(mx < a[cur][j])
{
mx = a[cur][j];
pos = j;
}
}
ans.push_back(pos);
for(int i = 1;i <= n;++i)
a[i][pos] = 0;
}
sort(ans.begin(),ans.end());
for(auto x:ans)
cout << x << " ";
cout << "\n";
}
}

H. 0 and 1 in BIT

操作在无符号整型中表示为 ,在有符号整型中表示为 ,由于最终只保留 位没有超过 表示范围,可以考虑从有符号整型角度出发,最后保留 位即可。

对于 使得 ,当已经经历奇数次 操作时, 相当于 , 偶数次时相当于 ;考虑能否用前缀和预处理使得每次可直接查询 区间内的等价操作 ,最终答案直接使 加上 即可。

手动操作几次后发现实际情况还到 为止 的奇偶性有关,因为我们开始操作时作用在 上的 数量为 ,而数组 记录的是 整个过程的操作。因此 为奇数时应减去 。同时,若 为奇数,最后答案还要取反。

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
77
78
79
#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
typedef long long ll;
ll pre[N];
ll add[N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int n,q;
cin >> n >> q;
string s;
cin >> s;
for(int i = 1;i <= n;++i)
{
add[i] = add[i - 1];
pre[i] = pre[i - 1];
if(s[i - 1] == 'A')
{
add[i] ^= 1;
}
else
{
if(add[i])
{
pre[i]--;
}else
{
pre[i]++;
}
}
}
ll ans = 0;
for(int i = 1;i <= q;++i)
{
unsigned long long l,r;
string x;
cin >> l >> r >> x;
int L = min((l ^ ans) % n + 1,(r ^ ans) % n + 1);
int R = max((l ^ ans) % n + 1,(r ^ ans) % n + 1);
ll mx = 1ll << x.length();
ll cur = 0;
for(int i = 0;i < x.length();++i)
{
if(x[i] == '1')
{
cur += (1ll << ((ll)x.length() - i - 1));
}
}
if(!add[L - 1])
{
ans = (cur + pre[R] - pre[L - 1]) & (mx - 1);
}else
{
ans = (cur + pre[L - 1] - pre[R]) & (mx - 1);
}
if(add[L - 1] ^ add[R])
{
ans = (mx - 1) - ans;
}
ll temp = ans;
string out;
while(out.size() < x.size())
{
if(temp & 1)
{
out = out + "1";
}else
{
out = out + "0";
}
temp /= 2;
}
reverse(out.begin(), out.end());
cout << out << "\n";
}
}