[Daimayuan] 弗拉德和糖果 II(C++,数学)

不久前,弗拉德过生日,他收到了一包糖果。有 n n n 种糖果,第 i i i 种糖果有 a i a_i ai 个( 1 ≤ i ≤ n 1≤i≤n 1in)。

弗拉德决定每次只吃一个糖果。为了从吃东西中获得最大的乐趣,弗拉德不想连续吃两个相同类型的糖果。

帮助他弄清楚他是否可以在不连续吃两个相同的糖果的情况下吃掉所有的糖果。

简而言之,给定 n n n 个正整数 a i a_i ai a i a_i ai 表示有 a i a_i ai i i i,找到是否存在一种序列,使得所有的数都用上,且不存在 i i i 连续的情况

输入格式:

第一行,包含一个整数 n n n。 第二行,包含 n n n 个正整数。

输出格式:

输出一行,如果存在,输出YES,否则输出NO

样例输入
2
1 1
样例输出
YES
说明

只有两种情况:

1 2
2 1

无论先吃哪种糖果,都能吃完且不连续吃相同类型的糖果

数据限制

对于 100 % 100\% 100% 的数据,保证 1 ≤ n ≤ 5000000 , 1 ≤ a i ≤ 2 30 1≤n≤5000000,1≤a_i≤2^{30} 1n5000000,1ai230

解题思路:

因为要求不能连续吃相同的糖果,所以我们预先把相同糖果间留出空隙

我们只关心糖果之间的空隙能否被填充,并不关心之前或者之后有没有其他糖果,也不关心空隙之间到底有多少颗糖果

那么假设在吃 a i a_i ai糖果之前,已经排好了 s u m sum sum颗糖果

(1)如果有 s u m ≥ a i − 1 sum \ge a_i - 1 sumai1,则可以顺利吃掉 a i a_i ai糖果(空隙可以填充),同时更新 s u m sum sum,回到(1)

(2)但是如果条件不成立,那么我们就会剩下 a i − s u m − 1 a_i-sum-1 aisum1颗糖果等待被吃

(3)然后我们接收下一个输入 a i + 1 a_{i+1} ai+1,如果 a i + 1 a_{i+1} ai+1大于剩余糖果数量,则可以顺利吃掉 a i a_i ai糖果;反之更新剩余糖果数量和 s u m sum sum后回到(3)等待下一次输入

(4)在顺利吃掉 a i a_i ai糖果之后,要判断 a i + 1 a_{i+1} ai+1是否能被吃掉,能的话回到(1),反之回到(3)

注:当sum > max_a的时候,无论接下来的输入糖果数量是多少,我们都可以吃掉,所以不用继续累计 s u m sum sum,也就不用担心爆精度问题

AC代码如下

#include <stdio.h>
#include <stdlib.h>
const int max_n = 5e6;
const long long max_a = 2ll << 30;

int main() {
	int n;
	scanf("%d", &n);
	long long a, sum = 0, buffer = 0;
	for (int i = 0; i < n; i++) {
		scanf("%lld", &a);
		if (sum <= max_a) {
			if (!buffer) {
				if (sum >= a - 1) sum += a;//(1)
				else {//(2)
					sum = sum * 2 + 1;
					buffer = a - sum - 1;
				}
			}
			else {//(3)
				if (a >= buffer) {
					sum += buffer;
					if (sum >= a - 1) {
						sum += a;
                        buffer = 0;//return (1)
					}
					else {
						sum = sum * 2 + 1;
						buffer = a - sum - 1;//return (3)
					}
				}
				else {
					buffer -= a;
					sum += 2 * a;
				}
			}
		}
	}
	if (sum > max_a || !buffer) printf("YES");
	else printf("NO");
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WitheredSakura_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值