【国集作业】【AGC016B】Colorful Hats【思维题】

有点像小学奥数有木有??
小视野链接
洛谷链接

题目大意

一群人戴帽子,每个人报出除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=n1 a1<n/2 a 1 < n / 2 时可行:

A=n1 A = n − 1 相当于每人帽子颜色不同,颜色数为 n n ;否则颜色数必须为A个且要轮回至少两遍。(比如 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 cntb个数为 B B
有结论:cnta个取值为 A A 的数中的人的帽子颜色不与任何人相同。(可用反正法理解)。这时后cntb个数同为 BA B − A (减去前面的影响),先当成第一种情况特判是否合法,再算出后面的颜色个数,把它待会 A A 判断是否合法即可。

代码

其实有个Bug:当只有两人且a1=a2=1时,颜色数可为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;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值