B—闯关

这里写了两种种解法

  1. solve01是借鉴@jackle的题解,可以在题解区找到他的思路,这里我只是将他的思路写出来而已,具体思路还请浏览大佬的题解;
  2. solve03()是本人的思路,不过本人是小白,比赛时没有调出来,特写此篇题解加深理解。大致思路就是算出 h / k 的商( ave )和余数( temp ),余数的大小表示需要调整的数量(调整就是在 -ave 的基础上 -1 ),例如3 3 8 -3 0这组数据,可以构造-2,-3,-3,其中有两个数在 - ave(这里为-2) 的基础上 -1,两个数(即个数),就是对应的 temp
  • 为什么特判需要判断 h + ( k - 1 ) * r <= 0 呢?

-(这个特判是判断 r < 0 时的情况, r >= 0没必要)r 为可以设置的最大伤害,我们需要让骑士能走k步,如果我们将前 k - 1 个房间设置为伤害 r ,经过前 k - 1 步骑士的血量已经 <= 0 了(可能在其中的某一步就没血了),那骑士最多才能走 k - 1 步,根本就走不到 k 步,所以结果为 impossible

具体思路请看代码,写了非常详细的注释

//		https://ac.nowcoder.com/acm/contest/93002/B
//		*	*	*


#include<bits/stdc++.h>
using namespace std;
#define int long long

int n,k,h,l,r;
int a[100005];
void solve01(){
	cin>>n>>k>>h>>l>>r;
	if(h+k*l>0 || h+(k-1)*r<=0)//这里需要long long
		cout<<"impossible"<<endl;
	else//h/k>=l,如果相等,则k*l==h,否则 -h/k > l(这里l肯定<0,要是l>=0,早在if的时候就判断为无解了
	{	//所以以下else的部分 l<0 恒成立
		for(int i=1;i<k;i++)//将前k-1步设为r,第k步设为l
			a[i]=r;
		a[k]=l;
		int s=r*(k-1)+h+l;//s表示剩余的血量
		if(s>0)//如果这样设置s>0的话,说明血量多了,需要调整前k-1步
		{
			for(int i=k-1;i>=0;i--)//从第k-1步开始逆序调整
			{
				if(s>r-l)//第i步从r -> l,可以减少的血量为(r-l),如果(r-l)不够抵消这s滴血的话,那就需要再调整前面的i-1步
				{
					a[i]=l;//将第i步的r改成l
					s-=r-l;//s减去(r-l)
				}
				if(s<=r-l)
				{//s<=(r-l),那就不用再调整i-2步了,只需要将第i-1步设置成一个值,使得s能变成0,这个值就是r-s,第i-1步从r -> (r-s),血量减少s
					a[i-1]=r-s;
					break;
				}
			}
		}
		for(int i=k+1;i<=n;i++)
			a[i]=l;
		for(int i=1;i<=n;i++)
			cout<<a[i]<<" ";
	}
}

void solve03()
{
	cin>>n>>k>>h>>l>>r;
	if(h+k*l>0 || h+(k-1)*r<=0)//long long
		cout<<"impossible"<<endl;
	else if(h/k<-r)//要是ave=h/k < -r(即r的绝对值 > h/k),那就不能取ave了
	{			   // 5 5 17 -5 -4					5 5 24 -5 -4可以取ave
		for(int i=0;i<n-1;i++)
			cout<<r<<" ";
		cout<<l<<endl;
	}
	else//h/k>=l,如果相等,则k*l==h,否则 -h/k > l(这里l肯定<0,要是l>=0,早在if的时候就判断为无解了
	{	//所以以下else的部分 l<0 恒成立
		int ave=h/k,temp=k-h%k;//temp记为不需要-1的次数
		for(int i=1;i<=k;i++)
		{
			if(temp>0)//应该先输出没有-1的数
			{
				cout<<-ave<<" ";	//例如:5 5 3 -3 0
				temp--;				//h/k商为0,余数为3,要是将if-else交换顺序,那就输出 -1 -1 -1 0 0,这才走了3步
			}						//而应该构造0 0 -1 -1 -1五步,所以应该先输出没有-1的
			else
				cout<<-ave-1<<" ";//再输出-1的数
		}//这里不用担心-ave-1会超过l,肯定不会,因为经过第一重的无解判断,我们知道h+k*l<=0恒成立,
		//也就是l<=-h/k,要是等于,那就说明h能整除k,余数就是0,直接输出k个ave就是了,否则l至少比-h/k小1,所以-ave-1肯定不会超过l
		for(int i=k+1;i<=n;i++)
			cout<<l<<" ";
	}
}

signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0), cout.tie(0);
	//solve01();
	solve03();
	return 0;
}