Educational Codeforces Round 88 部分题解
A. Berland Poker
题意:
给定 \(n\) 张牌,其中有 \(m\) 张小丑牌,分成 \(k\) 份,记录每个人的小丑牌个数,求(最大个数-次大个数)的最大值。
思路:
贪心的想,使得最大个数尽可能大,并且次大个数尽可能小,接下来分类讨论:
①小丑牌个数\(\le\)手牌上限,\(m\le \frac{n}{k}\):此时可以让一个人拿完小丑牌,最大个数为 \(m\),次大个数为 \(0\),答案为 \(m\)。
①小丑牌个数\(>\)手牌上限,\(m> \frac{n}{k}\):此时可以让一个人拿满小丑牌,剩下的 \(m-\frac{n}{k}\) 张小丑牌尽可能均分给剩下的人,使得次大个数最小,此时最大个数为 \(\frac{n}{k}\),次大个数为 \(\lceil\frac{m-\frac{n}{k}}{k-1}\rceil\),答案为 \(\frac{n}{k}-\lceil\frac{m-\frac{n}{k}}{k-1}\rceil\)。
代码
点击查看代码
void solve() {
int n, m,k;
cin >> n >> m>>k;
int p=min(m,n/k);
int ans=p-(m-p+(k-2))/(k-1);
cout<<ans<<endl;
}
B. New Theatre Square
题意:
给定一个黑白矩阵,1*1的格子代价为 \(x\),1*2的格子代价为 \(y\),求涂黑的最小代价。
思路:
贪心,分类讨论:
①\(x*2\le y\):全部用1*1。
①\(x*2> y\):能用1*2就用,其他的用1*1。
代码
点击查看代码
void solve() {
int n, m,x,y;
cin >> n >> m>>x>>y;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char c;
cin>>c;
a[i][j]=(c=='.');
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(j+1<=m){
if(a[i][j]==a[i][j+1]&&a[i][j]==1){
ans+=min(x*2,y);
j++;
}else{
if(a[i][j]){
ans+=x;
}
}
}else{
if(a[i][j]){
ans+=x;
}
}
}
}
cout<<ans<<endl;
}
C. Mixing Water
题意:
给定 \(h,c,t\),循环操作,加入一个 \(h\),加入一个 \(c\),求平均值最接近 \(t\) 的最少次数。
思路:
当 \(h\) 和 \(c\) 的次数相等时,平均值为 \(\frac{h+c}{2}\),最少次数为 2。
当 \(h\) 和 \(c\) 的次数不相等时,不妨设 \(h\) 的次数为 \(x+1\),\(c\) 的次数为 \(x\)。
则平均值为 \(\frac{h\cdot (x+1)+c\cdot x}{2x+1}=\frac{h+c}{2}+\frac{h-c}{4x+2}\)。
此函数为单调函数,我们可以直接计算或者二分得到最接近 \(t\) 的左右两个点,然后比较,得到最小值和最少次数。
代码
点击查看代码
void solve() {
int n, m,x,y;
cin >> n >> m>>x>>y;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char c;
cin>>c;
a[i][j]=(c=='.');
}
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(j+1<=m){
if(a[i][j]==a[i][j+1]&&a[i][j]==1){
ans+=min(x*2,y);
j++;
}else{
if(a[i][j]){
ans+=x;
}
}
}else{
if(a[i][j]){
ans+=x;
}
}
}
}
cout<<ans<<endl;
}
D. Yet Another Yet Another Task
题意:
给定数组,求(区间和-区间最大值)的最大值。
思路:
值域很小,直接枚举区间最大值 \(x\),然后遍历数组,使得选取区间最大值小于等于 \(x\),记录答案即可。
代码
点击查看代码
int a[N];
void solve() {
int n;
cin >> n;
for (int i = 0; i < n; ++i) cin >> a[i];
int ans = 0;
for (int m = -30; m <= 30; ++m) {
int c0 = -INF, c1 = -INF, b = -INF;
for (int x : a) {
if (x > m) {
c0 = c1 = -INF;
} else if (x == m) {
int t = max(c0, c1);
if (t > -INF / 2) c1 = max(x, t + x);
else c1 = x;
c0 = -INF;
b = max(b, c1);
} else {
if (c0 > -INF / 2) c0 = max(x, c0 + x);
else c0 = x;
if (c1 > -INF / 2) {
c1 = c1 + x;
b = max(b, c1);
}
}
}
if (b > -INF / 2) ans = max(ans, b - m);
}
cout << ans << endl;
}
E. Modular Stability
题意:
有多少个数组满足$ (((x \bmod a_1) \bmod a_2) \dots \bmod a_{k - 1}) \bmod a_k = (((x \bmod a_{p_1}) \bmod a_{p_2}) \dots \bmod a_{p_{k - 1}}) \bmod a_{p_k}$ 对任意排列 \(p\) 成立。
思路:
结论题/证明题
结论:题意条件等价于数组的最小值能够整除数组里的任意数。
然后用组合数计数即可。
代码
点击查看代码
void solve() {
init();
int n, k;
cin >> n >> k;
int ans = 0;
for (int i = 1; i <= n; i++) {
int v = n / i;
if (v >= k) {
ans = (ans + C(v-1, k-1)) % mod;
}
}
cout << ans << endl;
}

浙公网安备 33010602011771号