数数字

今天中午1小时,定时两道,我就知道自己的太阳降落了。。。orz
在这里插入图片描述

题目

PB 带来了若干只蒟蒻。
众所周知,NTF 是数论学会的会长,于是 PB 准备用数字击败 NTF,以证明 PB 比 NTF 更强。
于是 PB 准备了一些卡片,并在每个蒟蒻头上都贴了一张卡牌。每个卡牌上都写了一个数字。
由于蒟蒻太弱了,甚至不会看镜子来了解自己头上的数字,但他们由于经常被大佬吊打,所以观察力敏锐,他们都知道别人头上的数字。

第 i 个蒟蒻会告诉你他看到了 ai 种数字(定义两个数字不同种当且仅当它们的值不同)

但是由于蒟蒻太弱了,可能会报错数据,NTF 需要核实是否有一种情况使所有蒟 蒻说的话都正确。(可能情况不唯一)

输入格式
多组测试,文件第一行一个整数 T,表示测试数据组数;
对于每组数据,第一行,一个整数 n,表示蒟蒻的数量;
第二行,n 个整数用空格隔开,表示数组 ai,意义同题面。
输出格式
如果至少有一种情况使所有蒟蒻的话都正确,输出"yes",否则,输出"no"。

样例
样例输入
2
2
1 1
4
1 3 2 2
样例输出
yes
no
数据范围与提示
对于所有数据,T<=10
对于 20% 的数据,N≤8
对于所有数据,1≦N≤1000000, 0≦ai<N

题解

首先,我们应该明确的最好找的规律就是:

看到的种类的最大值Max和最小值Min的差不应该超过1

证明:假设i看到了x种,j最大的情况也就是i是唯一的数字,而有k的数字与j相同,
这样也最多是看见了x+1种。

这样我们接下来就只用分类讨论Max = Min和Max = Min + 1的情况

1.Max = Min:
(1)显而易见,当Max + 1 = n时,是成立的,每一个i都是独一无二的数字
(2)当Max * 2 <= n时也是成立的,因为要维持i看到的种类不变,就必须至少要有一个a[j]=a[i]
所有要保证每个数至少出现两次

2.Max = Min + 1:有点杂,请仔细品味!!
我们先假设i报出的数有a[j]=a[i]的情况,那么就意味着i报出的数一定是Max

证明:设i报出了a[i],如果有a[j]=a[i],它就相当于照了一面镜子,看得见自己的数,
它报出的种类中有一种是自己,即Max,而如果i是独一无二的数字,它报出的种类就会少一种,即Min

所以,报出的数是Min的数的i头顶上的数是独一无二的
在这里插入图片描述
所以当我们确定了报出Min的i的个数有tot个的时候,剩下的n-tot个人报的就都是Max了
而对于这Max的考虑就可以变为情况1的做法

这里送几组数据给大家:

na[i]yes/no
52 2 3 3 3yes
52 2 2 3 3no
52 2 2 2 3no
31 2 2yes
73 4 4 4 4 4 4yes
63 4 4 4 4 4no
42 2 2 1yes

在这里插入图片描述

代码实现

如果有的犇犇被数据卡了,可以加个读入优化,还可以把第二个tot循环并到第一个里面
但是本xxjAC了,我就不改了。。

#include <cstdio>
#include <iostream>
using namespace std;
#define MAXN 1000005
int t, n, Min, Max;
int a[MAXN];
int main() {
	scanf ( "%d", &t );
	while ( t -- ) {
		scanf ( "%d", &n );
		Min = 0x7f7f7f7f;Max = 0;
		for ( int i = 1;i <= n;i ++ ) {
			scanf ( "%d", &a[i] );
			Min = min ( Min, a[i] );
			Max = max ( Max, a[i] );
		}
		if ( Max - Min > 1 ) printf ( "no\n" );
		else {
			if ( Max == Min && ( Max == 1 || Max == n - 1 ) ) printf ( "yes\n" );
			else {
				if ( Max == Min )  {
					if ( ( Max << 1 ) <= n || Max + 1 == n ) printf ( "yes\n" );
					else printf ( "no\n" );
				}
				else {
					int tot = 0;
					for ( int i = 1;i <= n;i ++ )
						if ( a[i] == Min ) tot ++;
					if ( ( ( Max - tot ) << 1 ) <= ( n - tot ) && tot < Max ) printf ( "yes\n" );
					else printf ( "no\n" );
				}
			}
		}
	}
	return 0;
}

把这道题甩在这儿啦,这里是励志要做进中国前100强的公司,有问题请call:139红酒白酒葡萄酒
有不理解的或者补充的欢迎大犇在评论区留言。。。
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值