2022“杭电杯”中国大学生算法设计超级联赛(1)补题

1011 Random

[0,1]生成n个数,m次操作,每次有1/2概率删除最大值,1/2概率删除最小值,问最终期望总和模1e9+7

思路:答案是(n-m)/2,即(n-m)*inv(2)

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
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int mod=1e9+7;
ll ksm(ll a,ll b){
ll ans=1,base=a%mod;
while(b){
if(b&1)
ans=ans*base%mod;
base=base*base%mod;
b>>=1;
}
return ans;
}
ll inv(ll x){
return ksm(x,mod-2)%mod;
}
int main(){
IOS
int t;
cin>>t;
while(t--){
int n,m;
cin>>n>>m;
cout<<(n-m)*inv(2)%mod<<endl;
}
}

1012 Alice and Bob

Alice和Bob玩游戏,有n个数在黑板上,当数中没有0的时候,Alice可以选择把这些数分为两个集合,然后Bob可以选择删掉其中一个集合的所有数,并将另一个集合中的数全部减去1,重复直至当黑板上出现0时,Alice胜利,否则当黑板上所有的数都被删掉时,Bob胜利

思路:如果一开始就有0,Alice胜,否则看最后1的个数是否大于2(这种情况下分区间并且减一就会出现至少1个0),1的数量大于2就Bob胜,否则Alice胜

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
const int maxn=1e6+5;
int n,a[maxn];
int main(){
IOS
int t;
cin>>t;
while(t--){
cin>>n;
for(int i=0;i<=n;i++)
cin>>a[i];
for(int i=n;i>=1;i--)
a[i-1]+=a[i]/2;
if(a[0])
cout<<"Alice"<<endl;
else
cout<<"Bob"<<endl;
}
}

1002 Dragon slayer

在一个(n,m)的区域内有k面墙
勇者从(xs+0.5,ys+0.5)出发到恶龙的位置( xt+0.5, yt+0.5)。
求勇者最少要消去多少面墙

思路:将每个坐标都乘以2,使0.5变成整数,我们发现最多只有15面墙,二进制枚举每一面墙的存在状态,对每种情况bfs,结果取最小

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(0),cin.tie(0)
using namespace std;
typedef long long ll;
const int N = 30 + 10;
int n, m, k;
int path[N], g[N][N], d[N][N];
int mi, xs, ys, xt, yt;
struct tk {
int x1, x2, y1, y2;
}wall[N];
struct T {
int x, y;
};
void init() {
memset(g, 0, sizeof g);
memset(d, 0, sizeof d);
d[ys][xs] = 1;
int x1, y1, x2, y2;
for(int i = 1; i <= k; i++) {
if(path[i]) {
x1 = wall[i].x1;
x2 = wall[i].x2;
y1 = wall[i].y1;
y2 = wall[i].y2;
x1 *= 2; x2 *= 2; y1 *= 2; y2 *= 2;
if(x1 == x2) {
for(int i = min(y1,y2); i <= max(y1,y2); i++) g[i][x1] = 1;
} else if(y1 == y2) {
for(int i = min(x1,x2); i <= max(x1,x2); i++) g[y1][i] = 1;
}
}
}
}
void bfs() {
int now = 0;
for(int i = 1; i <= k; i++) {
if(path[i] == 0)
now++;
if(now >= mi)
return;
}
queue<T> q;
q.push({xs,ys});
init();
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
while(q.size()) {
T t = q.front();
q.pop();
for(int i = 0; i < 4; i++) {
int x = t.x + dx[i], y = t.y + dy[i];
if(x >= 0 && y >= 0 && x <= n && y <= m && g[y][x] == 0 && d[y][x] == 0) {
if(x == xt && y == yt) {
mi = now;
return ;
}
q.push({x,y});
d[y][x] = 1;
}
}
}
}
void dfway(int u) {
if(u == k + 1) {
bfs();
return ;
}
path[u] = 1;
dfway(u + 1);
path[u] = 0;
dfway(u + 1);
}
void solve() {
cin >> n >> m >> k;
cin >> xs >> ys >> xt >> yt;
n *= 2; m *= 2; xs *= 2; ys *= 2; xt *= 2; yt *= 2;
xs++; ys++; xt++; yt++;
for(int i = 1; i <= k; i++) {
int x1, x2, y1, y2;
cin >> x1 >> y1 >> x2 >> y2;
wall[i] = {x1, x2, y1, y2};
}
mi = k;
dfway(1);
cout << mi << endl;
}
int main() {
IOS;
int t;
cin >> t;
while(t--)
solve();
}

代码参考自这个式姐不太冷