牛客暑期多校训练营1
发表于:2023-07-25 | 分类: 思维
字数统计: 1.1k | 阅读时长: 5分钟 | 阅读量:

摆了好久,开始准备自己的棺材本
更新至D,J,K…

题D

题意:在一个 nmn*m 且布满巧克力的二维平面上, ABA 和 B 两个人轮流操作,每次操作选择一个坐x,y(x, y),这时他能将 (1<=i<=x,1<=j<=y)(1<=i<=x,1<=j<=y) 上的巧克力都吃了,每个人操作时至少吃一个巧克力,谁吃最后一个巧克力则输。

解:当且仅当 n==mn==1(n == m || n == 1)KK吃最后一块。

1
2
3
4
5
6
7
8
9
10
11
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
#define A puts("Walk Alone")
#define K puts("Kelin")
int main(){
int n, m; cin >> n >> m;
if(n == m && n == 1) A;
else K;
}

题J

题意:AA 初始有 nn 元,他每次 gamble 花费 xx 元赌注,有 0.50.5 概率获胜,获胜则获得 2x2 * x 元, 反之无收获,问 AA 赚取 mm 元的概率是多少。其中 xx 初始值为 11, 若上一轮获胜则 x=1x = 1, 反之 x=x2x = x * 2, 对于概率 a=x/ya = x / y 满足 ay=xa * y = x MODMOD 998244353998244353 (1<=n,m<=1e91<=n,m<=1e9)

解:由题意得,倘若我们连续输了ii轮,那么第i+1i+1轮获胜的话就可以获得11元。对于 xx 元钱,最多只能输 lg=log2(x+1)lg = log2(x + 1) 次, 此时无法进行下一轮。此时我们必输的概率 p=12lgp = \frac{1}{2^{lg}}, 那么获胜的能获胜的概率即为 1p1 - p。同时我们发现,对于1,2)(1, 2)(3456)(3,4,5,6)7891011121314(7,8,9,10,11,12,13,14) ,这一些区间里,必输的场次是一样的,那么对于一个区间内相同的 pp, 我们可以使得ans=pow(p,场次数)ans *= pow(p, 场次数),这里我们用mxmx计算出每个区间的上限,从而得出场次数,由此解得。

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;
const int N = 2e5 + 10, MOD = 998244353;
ll qmi(ll a, ll b){
ll ans = 1;
while(b){
if(b & 1) ans = ans * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ans;
}
int main(){
ll n, m, ans = 1, sum = 0, x = 0, mx; cin >> n >> m;
for(ll x = n; x < m + n; x = mx){
ll lg = log2(x + 1);
ll p = (1 - qmi(qmi(2, lg), MOD - 2) + MOD) % MOD;
mx = min((1ll << (lg + 1)) - 1, m + n);
ans = ans * qmi(p, mx - x) % MOD;
}
cout << ans;
}

题K

题意:给定一个无向图和整数 kk,同时可以在两个已连的点间增加一点,操作次数不限。问距离11结点距离不超过KK的最大点数为多少。
解:由以下数据得出无向图。

1
2
3
4
5
6
7
8
9
10
8 9 3
1 2
1 3
1 5
3 4
3 6
4 5
5 6
6 7
7 8


其中我们可以将其处理为一颗拓扑型的树,得出每个结点到结点 11 的最短距离,如下图所示。

然后对于那些多余的边,就可以对答案 ans+=kdist[u]ans += k - dist[u], 同时对于如该样例的单条叶子结点 22 而言,其对答案的贡献为 kdist[2]k - dist[2]。最终得到如下的图,图中除结点 88 以外到结点 11 的距离都 <=k<=k

代码如下

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
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
vector<int> g[N];
int dist[N], pre[N];
int main(){
int n, m, k; ll ans = 0; cin >> n >> m >> k;
for(int i = 1; i <= n; ++ i) dist[i] = -1;
for(int i = 1; i <= m; ++ i){
int u, v; cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
queue<int> q;
dist[1] = 0;
q.push(1);
while(q.size()){
int u = q.front(); q.pop();
//if(dist[u] == -1) continue;
if(dist[u] <= k) ans ++;
for(auto &v: g[u]){
if(dist[v] == -1){
dist[v] = dist[u] + 1;
pre[v] = u;
q.push(v);
}else if(pre[u] != v) ans += max(k - dist[u], 0);
}
}
for(int i = 2; i <= n; ++ i){
if(dist[i] != -1 && g[i].size() == 1) ans += max(k - dist[i], 0);
}
cout << ans;
}
上一篇:
牛客暑期多校训练营2
下一篇:
傅里叶变换