The 2021 ICPC Asia Jinan Regional Contest

Solved A B C D E F G H I J K L M
2/13 - - Ø - - - - - - O - - -

题目链接

https://pintia.cn/problem-sets/1459829212832296960/problems/type/7

Problem C. Optimal Strategy

题意:

有 $n$ 件物品,第 $i$ 件的价值为 $a_i$。

A 和 B 轮流取物品,A 先手。

每个人都要最大化自己取到的物品的价值和,求有多少种可能的游戏过程。

思路:

记价值为 $i$ 的物品有 $cnt_i$ 个。

当剩余物品中最大价值为 $x$ 时:

  • 当 $cnt_x$ 为偶数时,当一个人取了 $x$ 后,下一个回合另一个人也必须取 $x$,下下回合可以随意取,这样最终每个人都能拿到 $\frac {cnt_x} {2}$ 个 $x$。
  • 当 $cnt_x$ 为奇数时,在一开始取走一个 $x$,转化为偶数情况。

按照物品价值从小到大考虑,记价值 $\le i$ 的物品有 $f_i$ 种游戏过程:

$f_i=f_{i-1}*cnt_i!*\binom{\lfloor\frac{cnt_i}{2}\rfloor+\sum_{j=1}^{i-1}{cnt_j}}{\lfloor\frac{cnt_i}{2}\rfloor}$。

代码:

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
#include <bits/stdc++.h>
#define SZ(x) (int)(x).size()
#define ALL(x) (x).begin(),(x).end()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
using namespace std;
typedef double DB;
typedef long double LD;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<LL> VLL;
typedef vector<PII> VPII;
// head
const int N=1e6+5;
const LL MOD=998244353;
int cnt[N];
LL fac[N],invfac[N],f[N],sum[N];
LL binom(int n,int m) {
return fac[n]*invfac[m]%MOD*invfac[n-m]%MOD;
}
LL qpow(LL a,LL b) {
LL ret=1;
while(b) {
if(b&1) ret=ret*a%MOD;
a=a*a%MOD;
b>>=1;
}
return ret;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;cin>>n;
fac[0]=1;
for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%MOD;
invfac[n]=qpow(fac[n],MOD-2);
for(int i=n-1;~i;i--) invfac[i]=invfac[i+1]*(i+1)%MOD;
for(int i=1;i<=n;i++) {
int x;cin>>x;
++cnt[x];
}
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+cnt[i];
f[0]=1;
for(int i=1;i<=n;i++) {
if(cnt[i]) f[i]=f[i-1]*fac[cnt[i]]%MOD*binom(cnt[i]/2+sum[i-1],cnt[i]/2)%MOD;
else f[i]=f[i-1];
}
cout<<f[n]<<'\n';
return 0;
}

Problem K. Search For Mafuyu

题意:

树形图,A 在点 $1$,B 可能在除了 $1$ 以外的任何点,概率是一样的。

A 要找到 B,如果 A 采取最优策略,求找到 B 的最小期望时间。

思路:

显然欧拉遍历所需步数是最少的。

代码:

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
#include <bits/stdc++.h>
#define SZ(x) (int)(x).size()
#define ALL(x) (x).begin(),(x).end()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define FI first
#define SE second
using namespace std;
typedef double DB;
typedef long double LD;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef vector<LL> VLL;
typedef vector<PII> VPII;
// head
const int N=105;
VI g[N];
LL sum,step;
void dfs(int u,int fa) {
for(auto v:g[u]) if(v!=fa) {
++step;
sum+=step;
dfs(v,u);
++step;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;cin>>T;
while(T--) {
int n;cin>>n;
for(int i=1;i<=n;i++) g[i].clear();
step=sum=0;
for(int i=1;i<n;i++) {
int u,v;cin>>u>>v;
g[u].PB(v);
g[v].PB(u);
}
dfs(1,0);
cout<<fixed<<setprecision(10)<<1.0*sum/(n-1)<<'\n';
}
return 0;
}