CF1774B-Coloring
挺有意思的一个思维题
题面翻译
Cirno_9baka 的纸条上有 个格子,他觉得空白的纸条看着有点无趣,于是想在纸条的格子上涂上 种颜色。同时,他认为第 种颜色必须要用 次,且每连续 个格子里涂的颜色必须互不相同。
Cirno_9baka 想知道有没有这样的一种涂色方案能符合他的要求。
Cirno_9baka has a paper tape with cells in a row on it. As he thinks that the blank paper tape is too dull, he wants to paint these cells with kinds of colors. For some aesthetic reasons, he thinks that the -th color must be used exactly times, and for every consecutive cells, their colors have to be distinct.
Help Cirno_9baka to figure out if there is such a way to paint the cells.
分析
这里用到了鸽笼原理 (鸽巢原理、抽屉原理、狄利克雷原理),鸽笼原理容易理解,但是活用并不容易。
将 个元素的集合划分成 个集合,则其中至少有一个集合中含有大于等于 。
那么活用鸽笼原理,一定要记住这一点:分清楚谁是苹果谁是抽屉。
这题的抽屉便是 , 的长度为一段,这一段内不能有重复。
那么我们可以算出段数,,这个段数上取整的意义是为了包括最后一段。即每段都是 段的段数加上模 的余数 , 就是最后一段内的数量 。
那么结合 考虑。
(1)如果 ,则无法构造出合法序列,最多只有 个盒子, 意味着一定有一个盒子中的数量 ,这里面蕴含了鸽笼原理的思想;
(2)如果有 个 ,且 ,也无法构造出合法序列,因为这 个 都是要往最后一段里加一个 的,所以当 时,必定有一个盒子重复。
(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
则是值域在 ,而前者是 。我们可以写成 n%k==0?n:n%k
。那么这里为什么要这么写呢?因为当 时, 被恰好分为 段,那么这时就没有多余的 也就无需这样操作。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话