题目大意
一群人戴帽子,每个人报出除ta以外所有人帽子颜色数量(设为 a1,a2…,an a 1 , a 2 … , a n ,保证 ai<=n a i <= n ),问是否有可行带帽方案。
题解
结论&思维题
先有结论:
ai
a
i
的极差小于2,否则不可行;
然后分两种情况:极差为0或为1考虑:
当极差为0(所有数相等(不妨设同为 A A ))时:或 a1<n/2 a 1 < n / 2 时可行:
A=n−1
A
=
n
−
1
相当于每人帽子颜色不同,颜色数为
n
n
;否则颜色数必须为个且要轮回至少两遍。(比如
n=5,A=2
n
=
5
,
A
=
2
,颜色可为12121);
(关于颜色数的计算会在下文中用到)
当极差为1时:
设排好序后,
A=a1,B=an
A
=
a
1
,
B
=
a
n
,有
cnta
c
n
t
a
个数为
A
A
,个数为
B
B
;
有结论:个取值为
A
A
的数中的人的帽子颜色不与任何人相同。(可用反正法理解)。这时后个数同为
B−A
B
−
A
(减去前面的影响),先当成第一种情况特判是否合法,再算出后面的颜色个数,把它待会
A
A
判断是否合法即可。
代码
其实有个Bug:当只有两人且时,颜色数可为1或2,我没特判居然过了。。
考场的代码十分混乱:
/**************************************************************
Problem: 3217
User: ezoixx118
****************************************************************/
//#pragma GCC optimize(3)
#include<iostream>
#include<iomanip>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<string>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#define ll long long
#define db double
#define mxlen 1000+9
#define inf 100009
#define INF (int)1e9
#define pi acos(-1)
#define rd(n) {n=0;char ch;int f=0;do{ch=getchar();if(ch=='-'){f=1;}}while(ch<'0'||ch>'9');while('0'<=ch&&ch<='9'){n=(n<<1)+(n<<3)+ch-48;ch=getchar();}if(f)n=-n;}
using namespace std;
int n;
int a[inf];
int main(){
rd(n)
for (int i=1;i<=n;i++){
rd(a[i])
}
sort(a+1,a+n+1);
if (a[n]-a[1]>1){
puts("No");
return 0;
}
if (a[n]-a[1]==0){
if (a[1]==n-1 || a[1]<=n/2){
puts("Yes");
}
else{
puts("No");
}
return 0;
}
int cnt1,cnt2;
for (int i=1;i<n;i++){
if (a[i]!=a[i+1]){
cnt1=i;
cnt2=n-i;
break;
}
}
if (a[1]<=cnt1-1){
puts("No");
return 0;
}
a[n]-=cnt1;
if (!a[n]){
puts("No");
return 0;
}
int col;
if (a[n]*2>cnt2){
col=cnt2;
}
else if (a[n]<=cnt2/2){
col=a[n];
}
else{
puts("No");
return 0;
}
if (col+cnt1-1!=a[1]){
puts("No");
return 0;
}
puts("Yes");
return 0;
}