CF1945H GCD is Greater

tags

模拟 优先队列

中文题面

给定长度为 n ( n ≥ 4 ) n(n \ge 4) n(n4) 的序列 a a a 和整数 x x x,将每个元素划分至 A A A 集合或 B B B 集合,要求 ∣ A ∣ , ∣ B ∣ ≥ 2 |A|,|B| \ge 2 A,B2 A A A 集合中所有元素的 gcd ⁡ \gcd gcd 严格大于 B B B 集合中所有元素的按位与加 x x x,即 gcd ⁡ y ∈ A { y } > AND ⁡ y ∈ B { y } + x \gcd _{y \in A} \{y\} > \operatorname{AND}_{y \in B}\{y\}+x gcdyA{y}>ANDyB{y}+x,给出方案或判断无解。

多测, 1 ≤ ∑ n , ∑ max ⁡ { a i } ≤ 4 ⋅ 1 0 5 1 \le \sum n,\sum \max \{a_i\} \le 4 \cdot 10^5 1n,max{ai}4105

思路

首先我们可以确定的是对于 g c d gcd gcd 我们只选两个数,因为选多了会让 g c d gcd gcd 变小,同时让按位与增大。

枚举每个二进制位:

  • 如果全是 1 1 1,那 按位与 确定是 1 1 1
  • 如果只有一个 0 0 0,如果 gcd ⁡ \gcd gcd 取到了这个 0 0 0 n − 1 n-1 n1 种选法)按位与 为 1 1 1,否则确定是 0 0 0
  • 如果只有两个 0 0 0,如果 gcd ⁡ \gcd gcd 取到了这两个 0 0 0 则 按位与 为 1 1 1,否则确定是 0 0 0

上述需要特判的位置对至多只有 O ( n log ⁡ n ) O(n\log n) O(nlogn) 对,直接判即可。

剩下的情况 按位与 确定。我们需要在被 ban 掉的位置对之外找到 gcd ⁡ \gcd gcd 最大的一对。

枚举 gcd ⁡ = d \gcd=d gcd=d,用调和的复杂度求出元素为 d d d 的倍数的个数 x x x 以及被 ban 掉的个数 y y y。如果 y < C x 2 y< C_x^2 y<Cx2,那我们能做到 gcd ⁡ = d \gcd=d gcd=d

然后暴力找即可

代码

#include <bits/stdc++.h>
#define N 400005
using namespace std;
int t,n,m,x,a[N],tmp[N],sump[N],sums[N],vis[N];
bool tag[N];
int gcd(int a,int b)
{
	if(a%b==0) return b;
	return gcd(b,a%b);
}
int main()
{
	cin >> t;
	while(t--){
		cin >> n >> x;
		for(int i=1;i<=n;i++) cin >> a[i];
		m=0;
		sump[0]=sums[n+1]=(1<<30)-1;
		for(int i=1;i<=n;i++) m=max(m,a[i]);
		for(int i=1;i<=m;i++) vis[i]=0;
		for(int i=1;i<=n;i++) tag[i]=0;
		for(int i=1;i<=n;i++) vis[a[i]]++;
		int ans1=-1,ans2=-1;
		for(int i=0;(1<<i)<=m;i++){
			if(ans1!=-1) break;
			int cnt=0;
			for(int j=1;j<=n;j++){
				if(!((1<<i)&a[j])) tmp[++cnt]=j;
			}
			if(cnt==1){
				for(int j=1;j<=n;j++){
					if(j==tmp[1]) sump[j]=sump[j-1];
					else sump[j]=sump[j-1]&a[j];
				}
				for(int j=n;j>=1;j--){
					if(j==tmp[1]) sums[j]=sums[j+1];
					else sums[j]=sums[j+1]&a[j];
				}
				for(int j=1;j<=n;j++){
					if(j==tmp[1]) continue;
					if(gcd(a[tmp[1]],a[j])>(sump[j-1]&sums[j+1])+x){
						ans1=tmp[1];ans2=j;
						break;
					}
				}
				if(!tag[tmp[1]]) tag[tmp[1]]=1,vis[a[tmp[1]]]--;
			}
			else if(cnt==2){
				for(int j=1;j<=n;j++){
					if(j==tmp[1]) sump[j]=sump[j-1];
					else sump[j]=sump[j-1]&a[j];
				}
				for(int j=n;j>=1;j--){
					if(j==tmp[1]) sums[j]=sums[j+1];
					else sums[j]=sums[j+1]&a[j];
				}
				for(int j=1;j<=n;j++){
					if(j==tmp[1]) continue;
					if(gcd(a[tmp[1]],a[j])>(sump[j-1]&sums[j+1])+x){
						ans1=tmp[1];ans2=j;
						break;
					}
				}
				for(int j=1;j<=n;j++){
					if(j==tmp[2]) sump[j]=sump[j-1];
					else sump[j]=sump[j-1]&a[j];
				}
				for(int j=n;j>=1;j--){
					if(j==tmp[2]) sums[j]=sums[j+1];
					else sums[j]=sums[j+1]&a[j];
				}
				for(int j=1;j<=n;j++){
					if(j==tmp[2]) continue;
					if(gcd(a[tmp[2]],a[j])>(sump[j-1]&sums[j+1])+x){
						ans1=tmp[2];ans2=j;
						break;
					}
				}
				if(!tag[tmp[1]]) tag[tmp[1]]=1,vis[a[tmp[1]]]--;
				if(!tag[tmp[2]]) tag[tmp[2]]=1,vis[a[tmp[2]]]--;
			}
		}
		if(ans1==-1){
			int res=a[1],g=-1;
			for(int i=2;i<=n;i++) res&=a[i];
			for(int i=m;i>=res+x+1;i--){
				int cnt=0;
				for(int j=i;j<=m;j+=i) cnt+=vis[j];
				if(cnt>=2){
					g=i;
					break;
				}
			}
			if(g!=-1){
				for(int i=1,now=0;i<=n;i++){
					if(vis[a[i]]&&a[i]%g==0){
						now++;
						if(now==1) ans1=i;
						else{
							ans2=i;
							break;
						}
					}
				}
			}
		}
		if(ans1==-1) cout << "NO\n";
		else{
			cout << "YES\n";
            cout << 2 << ' ' << a[ans1] << ' ' << a[ans2] << '\n';
			cout << n - 2;
			for(int i=1;i<=n;i++){
				if(i!=ans1&&i!=ans2) cout << ' ' << a[i];
			}
			cout << '\n';
		}
	}
	return 0;
}
### 安装或更新至 Microsoft Visual C++ 14.0 或更高版本 当遇到“Microsoft Visual C++ 14.0 or greater is required”的错误提示时,表明当前环境中缺失必要的编译器支持。为了成功安装依赖于这些工具的 Python 包,如 gensim 和 wordcloud,需按照如下方法操作。 #### 使用官方渠道获取并安装 Microsoft C++ Build Tools 访问微软官方网站下载页面,寻找适用于 Windows 的 **C++ 构建工具 (Build Tools)** 。该软件包包含了开发过程中所需的全部组件,包括但不限于编译器、链接器和其他构建工具[^1]。 完成上述步骤后,启动安装程序,并确保勾选了所有与 C++ 编译相关的选项,特别是那些涉及静态 CRT 支持的部分。这一步骤对于确保后续能够顺利编译源码至关重要[^2]。 #### 替代方案:通过预编译二进制文件绕过本地编译环境配置 如果不想经历完整的 Visual Studio 安装过程,则可以考虑利用第三方提供的已预先编译好的 wheel 文件来简化流程。具体做法是从可信站点查找对应平台架构(win_amd64, win32 等)下的.whl格式文件,之后借助 pip 工具直接进行离线安装[^4]。 ```bash pip install package_name‑version‑py3-none‑win_amd64.whl ``` 这里 `package_name` 应替换为目标库的实际名称;而 `version` 则指明特定版本号。请注意保持操作系统位数与whl文件相匹配。 #### 特定场景下可能还需要额外安装运行时库 除了开发者工具外,在某些情况下也需要单独部署 Microsoft Visual C++ Redistributable Packages 来满足应用程序正常工作所需的基础条件。可以从微软官网找到最新版红帽包并依照指示执行安装[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值