CF1774B-Coloring

挺有意思的一个思维题

题面翻译

Cirno_9baka 的纸条上有 n 个格子,他觉得空白的纸条看着有点无趣,于是想在纸条的格子上涂上 m 种颜色。同时,他认为第 i 种颜色必须要用 ai 次,且每连续 k 个格子里涂的颜色必须互不相同。

Cirno_9baka 想知道有没有这样的一种涂色方案能符合他的要求。

Cirno_9baka has a paper tape with n cells in a row on it. As he thinks that the blank paper tape is too dull, he wants to paint these cells with m kinds of colors. For some aesthetic reasons, he thinks that the i -th color must be used exactly ai times, and for every k consecutive cells, their colors have to be distinct.

Help Cirno_9baka to figure out if there is such a way to paint the cells.

分析

这里用到了鸽笼原理 (鸽巢原理、抽屉原理、狄利克雷原理),鸽笼原理容易理解,但是活用并不容易。

n 个元素的集合划分成 m 个集合,则其中至少有一个集合中含有大于等于 nm

那么活用鸽笼原理,一定要记住这一点:分清楚谁是苹果谁是抽屉。

这题的抽屉便是 kk 的长度为一段,这一段内不能有重复。

那么我们可以算出段数,v=nk,这个段数上取整的意义是为了包括最后一段。即每段都是 k 段的段数加上模 k 的余数 rr 就是最后一段内的数量 0r<k

那么结合 ai 考虑。

(1)如果 ai>v,则无法构造出合法序列,最多只有 c 个盒子,ai>v 意味着一定有一个盒子中的数量 2,这里面蕴含了鸽笼原理的思想;

(2)如果有 qai=v,且 q>r,也无法构造出合法序列,因为这 qai 都是要往最后一段里加一个 1 的,所以当 q>r 时,必定有一个盒子重复。

(3)除此之外都可行。

#include <bits/stdc++.h>

inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0' && ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}

using namespace std;

int main()
{
	int T = read();
	int n,m,k;
	while (T--) {
		n = read(), m = read(), k = read();
		int v = int(ceil(n*1.0/k)), a, f = 0, c = 0;
        // v 的取整特别严格,只有这么写才不会挂分
		for (int i = 1; i <= m; i++) {
			a = read();
			if (a > v) f = 1;
			if (a == v) c++;
		}
		if (f == 1) printf("NO\n");
		else if (c > (n  - 1) % k + 1) printf("NO\n");
		else printf("YES\n");
	}
    return 0;
}

关注程序的第21行,(n - 1) % k + 1 这个处理很妙。如果我们写 n%k 则是值域在 [0,k1],而前者是 [1,k]。我们可以写成 n%k==0?n:n%k。那么这里为什么要这么写呢?因为当 k|n 时,n 被恰好分为 k 段,那么这时就没有多余的 r 也就无需这样操作。

posted @   Vegdie  阅读(68)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示