XJOI 奋斗群群赛 14 解题报告
原题
https://cn.vjudge.net/contest/186844 (Codeforces Round #386 (Div. 2))
A - Compote
题意
给出三个数表示柠檬,苹果和梨的个数,做一个蛋糕需要1个柠檬,2个苹果,4个梨,问最多能做几个蛋糕.
题解
柠檬个数不变,苹果个数除以2,梨个数除以4,输出三个数最小的.
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b,c;
cin>>a>>b>>c;
b=b/2;
c=c/4;
int m=0;
m=min(a,b);
m=min(m,c);
cout<<m*7;
}
B - Decoding
题意
有一种编码规则,给出一串字符串,如果长度为奇数,取最中间的放在生成串的下一个位置,否则把(中间-1)的放在生成串的下一个位置,重复该步骤.现给出一串用这种方法处理的字符串,让你求原字符串.
题解
逆着推回去,分类讨论一下,字符串长度是奇数,将第一位放在最中间,之后分第奇数个,第偶数个分别向前向后放,偶数的一样,将前两位放在中间即可.
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,num,temp1=1,temp2=1;
cin>>n;
char c,ans[2010];
if(n%2==1){
num=n/2+1;
}
else num=n/2;
for(int i=1;i<=n;i++){
cin>>c;
if(n%2==1){
if(i==1) ans[num]=c;
else if(i%2==1) {
ans[temp1+num]=c;
temp1++;
}
else{
ans[num-temp2]=c;
temp2++;
}
}
else{
if(i==1)ans[num]=c;
else if(i==2) ans[num+1]=c;
else if(i%2==0){
ans[temp1+num+1]=c;
temp1++;
}
else{
ans[num-temp2]=c;
temp2++;
}
}
}
for(int i=1;i<=n;i++){
cout<<ans[i];
}
}
C - Tram
题意
有一辆电车在0-s的路上开,方向表示为d(从0到s或从s到0),开到终点后转向,每t1秒前进一米,初始位置为p,有一个人要从x1走向x2,每t2秒前进一米,这个人可以乘车前进,问到达x2的最短时间
题解
我们可以这样想:无论这个人中间上下车多少次,最终到达终点只有两种可能:走路到达,乘车到达,并且由于车速一定快,他一旦开始乘车,乘车到终点会比走路快,因此我们只要求出人步行到达终点的时间和车开到终点的时间后比较即可.
#include<bits/stdc++.h>
using namespace std;
int s,x1,x2,t1,t2,p,d;
int time0=0,dis=0,flag1=0,flag2=0;
int main(){
scanf("%d %d %d %d %d %d %d",&s,&x1,&x2,&t1,&t2,&p,&d);
if(x1>x2) flag1=1;
if(d==-1) flag2=1;
time0=abs(x2-x1)*t2;
if(x1==x2){
cout<<0;
return 0;
}
if(t2<=t1){
cout<<time0;
return 0;
}
if(flag1==1&&flag2==1){
if(p<x1){
t1=(2*s+p-x2)*t1;
}
else{
t1=(p-x2)*t1;
}
}
if(flag1==0&&flag2==0){
if(p<=x1){
t1=(x2-p)*t1;
}
else{
t1=(2*s+x2-p)*t1;
}
}
if(flag1==1&&flag2==0){
t1=(2*s-p-x2)*t1;
}
if(flag1==0&&flag2==1){
t1=(p+x2)*t1;
}
cout<<min(t1,time0);
return 0;
}
D - Green and Black Tea
题意
一个人有n杯茶,a杯绿茶,b杯红茶,他不能连续喝k杯茶以上,问喝茶方案.
题解
对于a,b,如果a=b,那么交替喝直到喝完即可,否则,从大的喝起,大的喝k杯,小的喝一杯,这样操作的话问题会逐渐趋向a=b的情况,如果发现按照这种做法时应该喝某种茶了可茶的数量却为0,输出”NO”;
#include <bits/stdc++.h>
using namespace std;
const int MAXN=100010;
typedef long long int ll;
char s[MAXN];
int main() {
int n, k, a, b, p = 0, i;
scanf("%d %d %d %d", &n, &k, &a, &b);
bool flag = 1, c;
if(a>b) {
int tmp = min(k, a-b);
for(i = 1; i <= tmp; i++) {
a--;
s[p++] = 'G';
}
c = 0;
} else if(b>a) {
int tmp = min(k, b-a);
for(i = 1; i <= tmp; i++) {
b--;
s[p++] = 'B';
}
c = 1;
} else {
for(i = 1; i <= a*2; i++) s[p++] = ((i%2==1)?'G':'B');
a = b = 0;
}
while(a||b) {
if(a==b) {
if(c) for(i = 1; i <= a*2; i++) s[p++] = ((i%2==1)?'G':'B');
else for(i = 1; i <= a*2; i++) s[p++] = ((i%2==1)?'B':'G');
break;
}
if(c) {
if(a==0) {
flag = 0;
break;
}
a--;
s[p++] = 'G';
int tmp = min(k, b-a);
for(i = 1; i <= tmp; i++) {
b--;
s[p++] = 'B';
}
c = 1;
} else {
if(b==0) {
flag = 0;
break;
}
b--;
s[p++] = 'B';
int tmp = min(k, a-b);
for(i = 1; i <= tmp; i++) {
a--;
s[p++] = 'G';
}
c = 0;
}
}
if(!flag) printf("NO\n");
else {
s[p] = '\0';
printf("%s\n", s);
}
}
E - Numbers Exchange
题意
一个人有n张牌,值为a1-an,另一个人有m张牌,值为1-m,问能否交换牌,使得第一个人手上的牌奇数个数和偶数个数相同且没有重复的牌
#
既然有重复出现的牌,首先进行去重,之后对于偶数的个数进行分类讨论.
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
vector<ll>V;
map<ll,ll>vis,cnt,a;
int main() {
int n,m,i,j,p;
scanf("%d%d",&n,&m);
for(i=1; i<=n; i++) {
scanf("%d",&a[i]);
if(vis[a[i]] || cnt[a[i]&1]==n/2) V.push_back(i);
else {
vis[a[i]]=1;
cnt[a[i]&1]++;
}
}
p=0;
for(i=1; i<=m; i++) {
if(p==V.size()) break;
if(vis[i]) {
continue;
}
if(cnt[i&1]<n/2) {
cnt[i&1]++;
a[V[p++]]=i;
}
}
if(p<V.size()) printf("-1");
else {
printf("%d\n",p);
for(i=1; i<=n; i++) printf("%d ",a[i]);
}
return 0;
}