Educational Codeforces Round 88

比赛链接 / 官方题解链接

A. Berland Poker

Solution

如果 jokers 数量小于等于手牌数量,就把所有 jokers 揽入自己手中;否则,剩余的 jokers 平摊给其他人。

Code

>folded
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;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define mp(x, y) make_pair(x, y)
#define pb(x) emplace_back(x)

int T, n, m, k;

int main(){
for(read(T); T; T--){
read(n, m, k);
if(m <= n / k) printf("%d\n", m);
else{
m -= n / k;
int d = m / (k - 1);
if(m % (k - 1)) d++;
printf("%d\n", n / k - d);
}
}
return 0;
}

B. New Theatre Square

Solution

对每一行单独计算,令 $y=\min\{y, 2x\}$,然后优先放 $1\times2$ 的瓷砖。

Code

>folded
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
#include<bits/stdc++.h>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define mp(x, y) make_pair(x, y)
#define pb(x) emplace_back(x)

int T, x, y, n, m;
char s[1005];

int main(){
for(read(T); T; T--){
read(n, m, x, y);
if(y > 2 * x) y = 2 * x;
LL ans = 0;
for(int i = 1; i <= n; i++){
scanf("%s", s+1);
for(int j = 1; j <= m; j++){
if(s[j] == '.'){
if(j < m && s[j+1] == '.'){
ans += y;
j++;
}
else ans += x;
}
}
}
printf("%lld\n", ans);
}
return 0;
}

C. Mixing Water

Solution

温度变化为:$h,\frac{h+c}{2},\frac{2h+c}{3},\frac{h+c}{2},\frac{3h+2c}{5},\frac{h+c}{2},\cdots$ 偶数项均为 $\frac{h+c}{2}$,奇数(第 $2k-1$)项为 $\frac{kh+(k-1)c}{2k-1}$.

由于所有温度均大于等于 $\frac{h+c}{2}$,所以如果 $t\leq\frac{h+c}{2}$,那么答案就是 $2$;否则,我们在奇数项中寻找最接近答案的一项。

设第 $k$ 项温度正好是 $t$,那么 $\frac{kh+(k-1)c}{2k-1}=t$,化简得:$k=\frac{t-c}{2t-h-c}$. 由于实际上不会正好等于,我们比较一下 $k-1,k,k+1$ 就好。

Code

>folded
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
#include<bits/stdc++.h>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define mp(x, y) make_pair(x, y)
#define pb(x) emplace_back(x)

int T;
LL c, h, t;

inline double tem(LL k){
return (double)(k * h + (k-1) * c) / (2*k-1);
}

int main(){
for(read(T); T; T--){
read(h, c, t);
if(t <= 0.5 * (h + c)){
puts("2");
continue;
}
LL k = (t - c) / (2 * t - h - c);
LL ans = 2; double mn = t - 0.5 * (h + c);
if(fabs(tem(k) - t) < mn){
mn = fabs(tem(k) - t);
ans = 2 * k - 1;
}
k--;
if(fabs(tem(k) - t) < mn){
mn = fabs(tem(k) - t);
ans = 2 * k - 1;
}
k += 2;
if(fabs(tem(k) - t) < mn){
mn = fabs(tem(k) - t);
ans = 2 * k - 1;
}
printf("%lld\n", ans);
}
return 0;
}

D. Yet Another Yet Another Task

Solution

注意到 $-30\leq a_i\leq30$ 范围很小,所以枚举最大值 $mx$,然后 $dp$ 寻找最大子段和,且子段中最大值不大于 $mx$.

设 $dp[i]$ 表示以 $a[i]$ 结尾的最大子段和($a[i]$ 必选),并且要满足这个子段中最大值不大于 $mx$;设 $st[i]$ 表示这个最大子段和的起始位置,那么容易有 $dp$ 方程:$dp[i]=\begin{cases}-INF,&a[i]>mx\\dp[i-1]+a[i],&a[i]\leq mx\and dp[i-1]\geq0\\a[i],&a[i]\leq mx\and dp[i-1]<0\end{cases}$,对应有 $st[i]=\begin{cases}无,&a[i]>mx\\st[i-1],&a[i]\leq mx\and dp[i-1]\geq0\\i,&a[i]\leq mx\and dp[i-1]<0\end{cases}$. 如果 $[i,st[i]]$ 中包含了 $mx$,就用 $dp[i]-mx$ 去更新答案。

Code

>folded
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
#include<bits/stdc++.h>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define mp(x, y) make_pair(x, y)
#define pb(x) emplace_back(x)

const int N = 100005;

int n, a[N], cnt[N][100], ans = -1e9;

int main(){
read(n);
for(int i = 1; i <= n; i++){
read(a[i]);
for(int j = -30; j <= 30; j++)
cnt[i][j+30] = cnt[i-1][j+30];
cnt[i][a[i]+30]++;
}
for(int mx = -30; mx <= 30; mx++){
vi dp(n+5, -1e9), st(n+5, 0);
for(int i = 1; i <= n; i++){
if(a[i] > mx) continue;
if(dp[i-1] < 0){
dp[i] = a[i];
st[i] = i;
}
else{
dp[i] = a[i] + dp[i-1];
st[i] = st[i-1];
}
}
for(int i = 1; i <= n; i++){
if(dp[i] == -1e9) continue;
if(cnt[i][mx+30] - cnt[st[i]-1][mx+30] > 0)
ans = max(ans, dp[i] - mx);
}
}
printf("%d\n", ans);
return 0;
}

E. Modular Stability

Solution

假设我们选取 $x=a_k$,那么取第一个模数为 $a_k$,可以知道答案应为 $0$;此时,若取第一个模数为 $a_1$,那么有:$a_k\bmod a_1=0$,也即 $a_k$ 是 $a_1$ 倍数;同理我们可以证明:$a_2,a_3,\cdots,a_k$ 均是 $a_1$ 的倍数。

至于有没有其他条件约束,我在比赛时没有去证明了(因为可以从样例中得到验证)。

所以我们枚举 $a_1$ 的取值,得到 $[1,n]$ 中 $a_1$ 的倍数的个数,设为 $m$,那么从这 $m-1$ 个数(剔除 $a_1$ 本身)选取 $k-1$ 个数作为 $a_2,a_3,\cdots,a_k$ 即可,所以共有 $C_{m-1}^{k-1}$ 中选法。

Code

>folded
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;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define mp(x, y) make_pair(x, y)
#define pb(x) emplace_back(x)

const LL MOD = 998244353;
const int N = 500005;

LL n, k, ans, fact[N], invfact[N];

inline LL fpow(LL bs, LL idx){
LL res = 1;
bs %= MOD;
while(idx){
if(idx & 1) (res *= bs) %= MOD;
(bs *= bs) %= MOD;
idx >>= 1;
}
return res;
}

inline LL C(LL m, LL r){
return fact[m] * invfact[r] % MOD * invfact[m-r] % MOD;
}

int main(){
fact[0] = 1, invfact[0] = 1;
for(int i = 1; i <= 500000; i++){
fact[i] = i * fact[i-1] % MOD;
invfact[i] = fpow(fact[i], MOD - 2);
}
read(n, k);
if(n < k) return puts("0");
for(LL i = 1; i <= n; i++){
LL cnt = n / i;
if(cnt < k) break;
(ans += C(cnt - 1, k - 1)) %= MOD;
}
printf("%lld\n", ans);
return 0;
}

作者

xyfJASON

发布于

2020-05-29

更新于

2020-12-20

许可协议

评论