CF1715B Beautiful Array 题解

21 篇文章 0 订阅

题面

CF原版
洛谷中文题面

分析

首先明确一点,所有数的和(为sum)一定时 ∑ i = 1 n a i k ⩽ s u m k \sum_{i = 1}^{n} \frac{a_i}{k} \leqslant \frac{sum}{k} i=1nkaiksum。因为如果你分出来了一个小于 k - 1 的数,剩下的数的和除以 k 要么减小 1,要么不变。而如果分出来的数大于 k - 1,那么一定可以表示成若干个 k 和一个小于 k - 1 的数的和的形式,很显然他减小的部分一定大于等于分出来这个数增加的部分(那若干个 k 就已经可以补上了,而那个小于 k - 1 可能使他更小)。

无解

首先分析无解情况,如果 s k < b \frac{s}{k} < b ks<b 则一定无解,还有另一种情况下面会说。

构造

我们可以不断地分出 k - 1 这样除了过后的和一定会不断减小,而且这样的做法一定是减的最多的,理由如上。因此我们只需要给最大的那个数留下 m i n ( s , k ∗ ( b + 1 ) − 1 ) min(s, k * (b + 1) - 1) min(s,k(b+1)1) ,剩下的一直分 k - 1 直到分不够为止即可,min 是为了考虑刚好是 b 的情况。当然,如果我们分满了 n - 1 个还有剩余,则是另一种无解情况,输出 -1 即可。

代码实现

//省略快读和头文件
int T;
ll n, k, b, s;
ll num[MAXN], cnt = 0;

int main()
{
	T = inpt();
	while(T--) {
		n = inpt(), k = inpt(), b = inpt(), s = inpt();
		if(s / k < b) {//无解情况 1
			puts("-1");
			continue;
		}
		cnt = 0;
		num[++cnt] = min(s, k * (b + 1) - 1);//留下的大数
		s -= num[cnt];
		while(s) {
			if(s > k - 1) {//不断的分
				num[++cnt] = k - 1;
				s -= k - 1;
			}else {//记得还可能有余
				num[++cnt] = s;
				s = 0;
			}
			
			if(cnt > n)//无解情况 2,这个也可以提前处理
				break;
		}
		
		if(cnt <= n) {
			for(int i = 1; i <= cnt; i++)
				printf("%lld ", num[i]);
			for(int i = cnt + 1; i <= n; i++)//记得剩下的要补 0
				printf("0 ");
			puts("");
		}else {
			puts("-1");
		}
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值