当前位置: 代码迷 >> 综合 >> Codeforces AIM Tech Round 3 (Div. 2)(A-D 未完)
  详细解决方案

Codeforces AIM Tech Round 3 (Div. 2)(A-D 未完)

热度:92   发布时间:2023-12-17 03:43:32.0

A. Juicer

题意:现在给你n个数,如果大于b,那就扔掉,否则加进去,如果加进去的和大于d,就清空一次,问清空次数
思路:简单模拟

代码:

#include<bits/stdc++.h>
using namespace std;
int n;
long long m,k;
int main(){scanf("%d%I64d%I64d",&n,&m,&k);int times=0;long long now=0;for(int i=0;i<n;i++){long long temp;scanf("%I64d",&temp);if(temp>m) continue;now+=temp;if(now>k){times++;now=0;}}printf("%d\n",times);
}

B. Checkpoints

题意:现在在一个直线上有n个点,你初始在一个点,现在你要跑过n-1个点,问最短跑多少
思路:统计好一开始在你位置上的点,在你左边的点,在你右边的点,排序,然后枚举跑左边点的数量,得出右边点的数量,不断更新最小值就好了,不过记得要特判下,一开始就跑好了,全跑左边和全跑右边的情况

代码:

#include<bits/stdc++.h>
using namespace std;
int n;
long long a[100100];
long long b[100100];
long long init;
int main(){scanf("%d%I64d",&n,&init);int times=0;int l=0;int r=0;for(int i=0;i<n;i++){long long temp;scanf("%I64d",&temp);if(temp==init)times++;else if(temp<init){a[l++]=temp;}elseb[r++]=temp;}sort(a,a+l);sort(b,b+r);long long minn=1e18;if(times>=n-1){printf("0\n");return 0;}for(int i=0;i<=l;i++){if(i==0&&r+times>=n-1){long long now=abs(init-b[n-times-2]);minn=min(minn,now);}else if(i>=n-1){long long now=abs(init-a[l-i]);minn=min(minn,now);}else if(n-1-(i+times)<=r){long long now=abs(init-a[l-i]);long long now2=abs(init-b[n-times-i-2]);now=min(now*2+now2,now+now2*2);minn=min(minn,now);}}printf("%I64d\n",minn);
}

C. Letters Cyclic Shift

题意:现在给你一个字符串,要把它的一个子串改变下,按照a->z,b->a,c->b。。。。的规律,问改变一次后所得字符串最小是多少
思路:优先改变前面的,改变到遇到a就停下,注意,必须要改变子串,所以还是要特判下全是a的字符串的情况

代码:

#include<bits/stdc++.h>
using namespace std;
char a[100100];
int main(){scanf("%s",a);int x=strlen(a);bool judge=false;for(int i=0;i<x;i++){if(i==x-1&&!judge){a[i]=(a[i]-'a'+25)%26+'a';break;}else if(a[i]!='a'){judge=true;a[i]--;}else if(judge&&a[i]=='a')break;}puts(a);
}

D. Recover the String

题意:给你四个数字,分别代表原字符串(原字符串只有’0’,’1’)的”00”,”01”,”10”,”11”这些子串的个数,分别是a1,a2,a3,a4,问存不存在原字符串,有的话输出原字符串,否则输出”Impossible”

思路:根据给的a1和a4,能够推算出原字符串的0,1的个数。
而对于字符串中任意一个’1’,它的后面每个’0’都会让a3加一,它前面每个’1’都会让a2数加一,对于每个’0’也是同理的,这样的东西出现了a3次(对于每个0也是同理的)。那么我就能推导出一个结论,如果有符合条件的字符串,那么必定有:0的个数*1的个数=a2*a3。
然后,从左向右来看,对于一个位置,它选1还是0,只是和剩下的0,1的个数有关,且对于后面的1,0的选择不产生影响,那么我就可以在这个地方选一个0,然后让0的个数减一,同时让a2减去目前1的剩余个数,直到a2小于了剩余1的个数,然后开始选1,不断重复上面的过程,直到1和0的剩余个数都是0为止。

但是,对于a1或者a4等于0的时候,我们需要考虑一个问题,那就是他们也是有可能没有,但是可能是有一个的,这个时候就需要特判了(必须吐槽下,这场BCD都是各种特判,wa到难受),如果中间两个数都是0,那么a1为0时,0个数就是0,a4同理,但是当a1,a4都是0的时候,就需要对a2,a3进行特判了,具体特判结果参考代码

到这里,这个题目的思路就算结束了,但是呢,我们可能会对我们的策略产生怀疑,为什么这样一个类似贪心的做法是正确的。首先,我们的a2,a3都会判断是否能产生一个符合题意得字符串,然后才会开始我们的贪心,而对于a2来说,a2必定大于等于0且小于等于1的个数*0的个数的,那么我们就能保证一定存在一种0的个数的加法使得其和为a2

代码:

#include<bits/stdc++.h>
using namespace std;
long long a[100100];
int main(){a[0]=0;int n;for(n=1;;n++){if(a[n-1]>1000000000)break;a[n]=a[n-1]+n;}long long q,w,e,r;scanf("%I64d%I64d%I64d%I64d",&q,&w,&e,&r);bool judge=false;int num0=lower_bound(a,a+n,q)-a;int num1=lower_bound(a,a+n,r)-a;if(q!=a[num0]||r!=a[num1])judge=true;if(num0==0&&num1==0){if(w==1&&e==0)printf("01\n");else if(w==0&&e==0)printf("0\n");else if(w==0&&e==1)printf("10\n");elseprintf("Impossible\n");return 0;}num1++;num0++;if(num0==1&&w==0&&e==0)num0=0;if(num1==1&&w==0&&e==0)num1=0;if(num0*num1!=w+e||judge){printf("Impossible\n");return 0;}else{while(num0!=0||num1!=0){if(w>=num1){printf("0");num0--;w-=num1;}else{printf("1");num1--;e-=num0;}}}puts("");
}

  相关解决方案