Educational Codeforces Round 88 (Rated for Div. 2) A - E 解题报告
题目链接
\(A. Berland Poker\)
\(Description:\)
给定 \(n\) 张牌,其中有 \(m\) 张特殊的牌,把所有牌平均分给 \(k\) 个人,问你手中的特殊牌的数量 \(-(k - 1)\) 个人中拥有最多特殊牌的数量的最大值是多少?
\(Solution:\)
先把特殊牌分给你,其他人在平均分即可。
\(Code:\)
/*
@Author: nonameless
@Date: 2020-05-29 09:20:42
@Email: 2835391726@qq.com
@Blog: https://www.cnblogs.com/nonameless/
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
int main(){
int t; cin >> t;
while(t --){
int n, m, k;
cin >> n >> m >> k;
int cnt = n / k;
if(cnt >= m) cout << m << endl;
else{
cnt -= (m - cnt) / (k - 1) + ((m - cnt) % (k - 1) != 0);
cout << cnt << endl;
}
}
return 0;
}
\(B. New Theatre Square\)
\(Description:\)
给定 \(n \times m\) 的矩阵,让你来用 \(1 \times 2\) 和 \(1 \times 1\) 的砖来填充矩阵中的 \(.\),砖只能横着放,问最小代价是多少?
\(Solution:\)
遍历每一行,算出连续的 \(.\) 的个数即可。
\(Code:\)
/*
@Author: nonameless
@Date: 2020-05-29 09:25:29
@Email: 2835391726@qq.com
@Blog: https://www.cnblogs.com/nonameless/
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
const int N = 1e2 + 10, M = 1e3 + 10;
int n, m, x, y;
char s[N][M];
int main(){
int t; cin >> t;
while(t --){
cin >> n >> m >> x >> y;
for(int i = 1; i <= n; i ++)
scanf("%s", s[i] + 1);
y = min(x + x, y);
int ans = 0;
for(int i = 1; i <= n; i ++){
int cnt = 0;
for(int j = 1; j <= m; j ++){
if(s[i][j] == '.') cnt ++;
else{
ans += cnt / 2 * y + (cnt % 2) * x;
cnt = 0;
}
}
ans += cnt / 2 * y + (cnt % 2) * x;
}
cout << ans << endl;
}
return 0;
}
\(C. Mixing Water\)
\(Description:\)
一杯热水的温度是 \(h\),一杯冷水的温度是 \(c\),按照热冷热冷热的顺序往桶里倒水,使其平均温度 \(tb\) 最接近 \(t\),问最少加几杯水?
\(Solution:\)
首先要知道的是如果我们加了偶数杯,也就是说热水和冷水各加了 \(x\) 杯,那么可以得到:\(\frac{x(h+c)}{2x} = \frac{h+c}{2}\),所以对于偶数杯的情况,就考虑完了。对于奇数杯,也就是在热冷各加了 \(x\) 杯后,再加了 \(1\) 杯热水,也就是说(设 \(a = h + c\)):
由于 \(h > \frac{a}{2}\),所以 \(tb\) 是关于 \(x\) 的递减函数,那么我们就可以二分解决了。
\(Code:\)
/*
@Author: nonameless
@Date: 2020-05-29 09:38:19
@Email: 2835391726@qq.com
@Blog: https://www.cnblogs.com/nonameless/
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
int h, c, t;
double calc(int cnt){ // 对于杯数下的平均温度
int a = cnt / 2, b = cnt % 2;
double res = (1ll * a * (h + c) + b * h) * 1.0 / cnt;
return res;
}
int main(){
int test; cin >> test;
while(test --){
cin >> h >> c >> t;
// first 是温度差,second 是杯数,优先按温度差排序
vector<pair<double, int> > vec;
vec.pb({fabs((h + c) / 2.0 - t), 2});
int l = 0, r = 1e9;
int more = 1, less = 1; // 一个大于 t, 一个小于等于 t
while(l <= r){
int mid = l + r >> 1;
int x = 2 * mid + 1; // 这样 x 就一定是奇数了
double tb = calc(x);
if(tb > t){
more = x;
l = mid + 1;
} else{
less = x;
r = mid - 1;
}
}
vec.pb({fabs(t - calc(less)), less});
vec.pb({fabs(t - calc(more)), more});
sort(all(vec)); // 排序
cout << vec[0].y << endl;
}
return 0;
}
\(D. Yet Another Yet Another Task\)
\(Description:\)
求某一段区间和减去区间的最大值后的所得得值最大可以是多少?特别得是 \(-30 \leq a_i \leq 30\)。
\(Solution:\)
题目已经明示了我们可以选择区间的最大值得只有 \([1, 30]\)(如果区间的最大值为负,那么我们为了结果最大,我们只有选长度为 \(1\) 的区间),所以我们就可以去枚举我们选出的区间的最大值,然后遍历整个数组,只要区间在此处不中断就与结果取 \(max\)。
\(Code:\)
/*
@Author: nonameless
@Date: 2020-05-29 14:32:55
@Email: 2835391726@qq.com
@Blog: https://www.cnblogs.com/nonameless/
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
const int N = 1e5 + 10;
int n, a[N];
int main(){
cin >> n;
for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
int ans = 0;
for(int i = 1; i <= 30; i ++){
int tmp = 0; // 连续的和
for(int j = 1; j <= n; j ++){
// 遇到比我们选择的区间最大值还大,就说明他一定不在我们所选的区间中,那么到这里区间就中断了,所以 tmp = 0;
if(a[j] > i) tmp = 0;
else{
tmp = max(0, tmp + a[j]); // 如果到这里区间和为负,那么我们应该舍弃掉
ans = max(ans, tmp - i);
}
}
}
cout << ans << endl;
return 0;
}
\(E. Modular Stability\)
\(Description:\)
给定 \(n,k\),让你构造一个长度为 \(k\) 的数组 \(a\),然后将 \(a\) 数组全排列得到 \(k!\) 个 \(p\) 数组,要求对于任意的 \(p\) 数组和任意一个 \(x > 0\) 满足:
特别的:\(1\leq a_1 < a_2 < ... < a_k\)。求 \(a\) 数组的个数?
\(Solution:\)
要让其任意顺序的模数都相等,那么他们肯定是要满足某种规律的。我就猜测数组 \(a\) 一定是满足了第一项是后面所有项的因子,这个也很好证明:
设数组 \(a\) :\(d,\ t_1d,\ t_2d,\ t_{k-1}d\)。那么 \(x\) 也可以和 \(d\) 挂上钩,即 \(x = kd + c\),对于去模 \(a\) 数组的结果显然是 \(c\),对于去模 \(p\) 数组,遇到比 \(x\) 大的不会变,比 \(x\) 小的,那么 \(x\) 就会逐渐变小,但是 \(c\) 是始终存在的,直到遇到 \(d\),变为 \(c\),而之后的数都比 \(c\) 大,显然 \(c\) 就是结果,与模 \(a\) 数组的结果一致,所以是可行的。
那么我们就可以去枚举 \(d\),然后算出 \([1,\ n]\) 中 \(d\) 的倍数的个数,排列组合即可求解。
\(Code:\)
/*
@Author: nonameless
@Date: 2020-05-29 11:25:26
@Email: 2835391726@qq.com
@Blog: https://www.cnblogs.com/nonameless/
*/
#include <bits/stdc++.h>
#define x first
#define y second
#define pb push_back
#define sz(x) (int)x.size()
#define all(x) x.begin(), x.end()
using namespace std;
typedef long long ll;
typedef pair<ll, ll> PLL;
typedef pair<int, int> PII;
const double eps = 1e-8;
const double PI = acos(-1.0);
const int INF = 0x3f3f3f3f;
const ll LNF = 0x3f3f3f3f3f3f;
inline int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
inline ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
inline int lcm(int a, int b) { return a * b / gcd(a, b); }
const int mod = 998244353;
const int N = 5e5 + 10;
ll f[N];
ll fPow(ll a, ll b){
ll res = 1;
while(b){
if(b & 1) res = res * a % mod;
b >>= 1;
a = a * a % mod;
}
return res;
}
ll C(int a, int b){
return f[a] * fPow(f[b] * f[a - b] % mod, mod - 2);
}
int main(){
int n, k;
cin >> n >> k;
f[0] = 1;
for(int i = 1; i <= n; i ++) f[i] = f[i - 1] * i % mod;
ll ans = 0;
for(int i = 1; i <= n; i ++){
int d = n / i - 1;
if(d < k - 1) break;
ans = (ans + C(d, k - 1)) % mod;
}
cout << ans << endl;
return 0;
}