题意:现在给你n个数,如果大于b,那就扔掉,否则加进去,如果加进去的和大于d,就清空一次,问清空次数
思路:简单模拟
#include
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;ilong long temp;
scanf("%I64d",&temp);
if(temp>m) continue;
now+=temp;
if(now>k)
{
times++;
now=0;
}
}
printf("%d\n",times);
}
题意:现在在一个直线上有n个点,你初始在一个点,现在你要跑过n-1个点,问最短跑多少
思路:统计好一开始在你位置上的点,在你左边的点,在你右边的点,排序,然后枚举跑左边点的数量,得出右边点的数量,不断更新最小值就好了,不过记得要特判下,一开始就跑好了,全跑左边和全跑右边的情况
#include
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;ilong long temp;
scanf("%I64d",&temp);
if(temp==init)
times++;
else if(tempelse
b[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);
}
题意:现在给你一个字符串,要把它的一个子串改变下,按照a->z,b->a,c->b。。。。的规律,问改变一次后所得字符串最小是多少
思路:优先改变前面的,改变到遇到a就停下,注意,必须要改变子串,所以还是要特判下全是a的字符串的情况
#include
using namespace std;
char a[100100];
int main(){
scanf("%s",a);
int x=strlen(a);
bool judge=false;
for(int i=0;iif(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);
}
题意:给你四个数字,分别代表原字符串(原字符串只有’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
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");
else
printf("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("");
}