CF1166E The LCMs Must be Large

CF1166E The LCMs Must be Large

思维好题,结论好题。

题意

一个长度为 n 的未知长度的序列,有 m 个限制,每个限制形如给定一个集合 S ,使集合内元素的 lcm 严格大于其补集元素的 lcm 。问是否存在这一序列。

思路

要注意我们是要尽可能使序列有解。

先给出结论:若所有集合两两间有交,则有解。否则一定无解。

首先有一个结论:若 AB,那么 lcmBlcmA

因为考虑 BA 多的元素,只可能增加贡献而不可能减少贡献,所以上述结论显然。

然后我们回到题目:若一个限制的集合 A 与另一个限制的集合 B 不交,假设 lcmA>lcmAS (S表示整个序列集合),那么一定有 BAS,即有 lcmASlcmB 。显然不符合要求。

然后证明结论的充分性。这里我们考虑一个构造的方法:假设所有元素初始都为1,我们将每个给定的集合内的元素都乘上一个互不相同的质数,那么如果集合两两相交,每个集合的lcm就是整个序列的lcm,并且每个集合的补集因为没有乘该集合的质数所以lcm一定小。如果有两个集合不相交,因为两个集合的质数不同,所以一定会出现一个集合的lcm大于另一个集合的情况,一定无解。

实现

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cstring>
#include<cmath>
#include<bitset>
using namespace std;
inline int read(){
	int w=0,x=0;char c=getchar();
	while(!isdigit(c))w|=c=='-',c=getchar();
	while(isdigit(c))x=x*10+(c^48),c=getchar();
	return w?-x:x;
}
namespace star
{
	const int maxn=1e4+10;
	int m;
	bitset<maxn> a[55],now;
	inline void work(){
		m=read();read();
	    for (int x,i=1;i<=m;i++) {
	        x=read();
	        while(x--)
	        	a[i].set(read());
	        for (int j=1;j<i;j++) {
	            if ((a[i] & a[j]).none())
					return (void)puts("impossible");
	        }
	    }
	    puts("possible");
	}
}
signed main(){
	star::work();
	return 0;
}
posted @   Star_Cried  阅读(112)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示