Educational Codeforces Round 112 (Rated for Div. 2)
A.PizzaForces
题意:6个蛋糕一盒15元,8个蛋糕一盒20元,10个蛋糕一盒25元,给你一个整数n,如何花最少的价格能购买n个蛋糕。
思路:每种买法的蛋糕单价是一样的,所以只要保证买的蛋糕超过n越少越好,我们可以发现任意的大于等于6的偶数都可以被6,8, 10的整数倍表示。所以当n % 2== 0 && n >= 6
答案就是单价乘以数量,当n % 2 == 1 && n > 6
的时候,买的蛋糕总数超过n最小的值是1,所以这个时候先n ++
再乘以单价。当然当n小于6的时候按照6买,花费最少。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n, ans;
int main()
{
int t;
cin >> t;
while(t -- ){
cin >> n;
if(n < 6) ans = 15;
else if(n % 2 == 0) ans = n * 5 / 2;
else ans = (n + 1) * 5 / 2;
cout << ans << endl;
}
return 0;
}
B.Two Tables
给你一个长为W,宽为H的区域S,里面有一个长方形A,长方形的左下坐标和右上坐标为(x1,y1),(x2,y2),再给你一个长为w,宽为h的小长方形B,问你将区域里面的长方形A最少移动多少单位,才能使小长方形放进区域且两个长方形没有重合区域,长方形的长要平行区域S的长,宽要平行区域S的宽,如果该区域不能同时放下这两个长方形,就输出“-1”。
思路:这道题其实只有上下移动或左右移动这两种情况,不存在斜着移动。
(1)假如你发现长方形B的长加上长方形A的长小于等于区域S 的长,那么你可以左右移动长方形A,
使长方形B能放进去,记录移动步数ans1。
(2)假如你发现长方形B的宽加上长方形A的宽小于等于区域S的 宽,那么你可以上下移动长方形A,使长方形B能放进去,记录移动步数ans2。
(3)如果 长方形B的长加上长方形A的长大于区域S 的长且长方形B的宽加上长方形A的宽大于区域S的宽,这种情况是不能同时放下两个长方形的,所以输出“-1”。
(4)答案就是(1)和(2)两个ans取个最小值。
代码:
#include <bits/stdc++.h>
// #define myl cout << "!!!!!!!" << endl;
using namespace std;
typedef long long LL;
double w, h, x1, x2, y1, y2, W,H;
void solve(){
scanf("%lf%lf%lf%lf%lf%lf%lf%lf",&W,&H,&x1,&y1,&x2,&y2,&w,&h);
if((x2 - x1 + w > W) && (y2 - y1 + h > H)){
printf("-1\n");
return;
}
double ans1 = 1e10, ans2 = 1e10, ans = 1e10;
if(h + y2 - y1 <= H){
double cha;
if(y1 >= H - y2){
cha = y1;
}else{
cha = H - y2;
}
if(cha >= h){
ans1 = 0;
}else{
ans1 =(double) (h - cha);
}
}
if(w + x2 - x1 <= W){
double cha;
if(x1 >= W - x2){
cha = x1;
}else{
cha = W - x2;
}
if(cha >= w){
ans2 = 0;
}else{
ans2 =(double) (w - cha);
}
}
if(ans1 < ans2) ans = ans1;
else ans = ans2;
printf("%.8lf\n",ans);
}
int main()
{
int _ = 1;
scanf("%d",&_);
while(_ -- ){
solve();
}
return 0;
}
C.Coin Rows
题意:给你一个2 * m的格子,每个格子上都有一个权值,Alice和Bob两个人玩游戏,从格子的左上端走到右下端,Alice先走,Bob后走。每个人走完后,得分为经过的地方的权值之和,且经过的地方权值变成0,Alice和Bob都希望自己的得分能高点,问你Bob的得分最少为多少。
思路:
假设红色是Alice走的,那么Bob会走经过A或者经过B的两条线路中每个格子上权值和最大的路。
所以这题只要枚举Alice走的路线的所有方式,然后依次将Bob选择路线上每个格子的权值和,取个最小值就行。要用前缀和优化。
代码:
#include <bits/stdc++.h>
using namespace std;
int m;
int a[100010];
int b[100010];
int suma[100010];
int sumb[100010];
int main()
{
int t;
cin >> t;
while(t -- ){
cin >> m;
int sum = 2e9;
int ans;
memset(suma,0,sizeof(suma));
memset(sumb,0,sizeof(sumb));
for(int i = 1; i <= m; i ++ ) cin >> a[i];
for(int j = 1; j <= m; j ++ ) cin >> b[j];
suma[1] = a[1], sumb[1] = b[1];
for(int i = 2; i <= m; i ++ ) suma[i] = suma[i - 1] + a[i];
for(int i = 2; i <= m; i ++ ) sumb[i] = sumb[i - 1] + b[i];
for(int i = 1; i <= m; i ++ ){
ans= max(sumb[i - 1],suma[m] - suma[i]);
sum = min(sum,ans);
}
cout << sum << endl;
}
}
D. Say No to Palindromes
题意:我们称一种字符串是beautiful的,该字符串中不包含长度大于1的回文串。题目给你一个只包含a,b,c三个字母的回文串,给你m次询问,每次询问给你l,r,问你在区间[l,r]中,将里面的一些字母改成a,b,c使该区间是beautiful的,问你最少的改变次数是多少。
思路:
(1)一共只有三个字母,那么构成回文的字符串只有六种情况:
{'a','b','c'}, {'a', 'c', 'b'}, {'b', 'a', 'c'}, {'b', 'c', 'a'}, {'c', 'a', 'b'}, {'c', 'b', 'a'}}
(2)最少次数一定是这六种情况的一种,枚举这六种情况,取让整个字符串变成beautiful的改变次数是最小的就行。
(3)本题是交互题,要用前缀和优化,先求出整个字符串前i个需要改变的总次数是多少,然后每次问答既可以直接调用前缀和。
代码:
#include <bits/stdc++.h>
using namespace std;
char a[6][3] = {{'a','b','c'}, {'a', 'c', 'b'}, {'b', 'a', 'c'}, {'b', 'c', 'a'}, {'c', 'a', 'b'}, {'c', 'b', 'a'}};
int sum[6][200010];
char s[200010];
int n, m;
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i ++ ) cin >> s[i];
for(int i = 0; i < 6; i ++ ){
for(int j = 1; j <= n; j ++ ){
sum[i][j] = sum[i][j - 1] + (s[j] != a[i][j % 3]);
}
}
int l, r;
while(m -- ){
cin >> l >> r;
int ans = r - l + 1;
for(int i = 0; i < 6; i ++ ){
ans = min(ans, sum[i][r] - sum[i][l - 1]);
}
cout << ans << endl;
}
}