首页 > 其他分享 >CF1945 H GCD is Greater

CF1945 H GCD is Greater

时间:2024-03-20 10:00:13浏览次数:33  
标签:20 数字 int CF1945 Greater GCD bs ll define

CF1945 H GCD is Greater

什么鬼啊 div3 H diff: 2775。
纯属码力题。
首先发现 \(\gcd\) 肯定数字越多越小。
然后与值数字越多越小。
所以结论就是选择两个数字取 \(\gcd\),剩下的数字分到另一个集合。
那么问题就变成了找出一对数字,它们的 \(\gcd\) 和剩下的数字的与做差值最大化。

怎么,是不是感觉这个问题还是非常抽象。
于是又开始人类智慧了。

发现如果数字非常多,与值很有可能等于 \(0\)。
于是我们在二进制位上面考虑问题。
现在我们考虑让与值为 \(0\)。
我们把某一位为 \(0\) 的数字个数记下来,那么如果这一位只有 \(1\) 个为 \(0\) 的数字,那么这个数字肯定不能取。
如果这一位只有 \(2\) 个为 \(0\) 的数字。那么这两个数字不能同时取。
也就是说最多只会有 \(19\) 条限制。
那如果不同数字的个数超过了 \(20\) 就一定可以使其与值为 \(0\)。

我们预处理 \(al_i\) 表示所有数字中第 \(i\) 位为 0 的数字个数。
于是我们枚举最大公约数 \(d\),考虑将它的倍数全部提出来,集合称为 \(bs\),以外的数字集合称为 \(out\)。
我们处理 \(in_i\) 表示集合 \(bs\) 中第 \(i\) 位为 0 的数字个数。
我们通过每一位的 \(al-in\) 可以快速求出集合 \(out\) 的与值。
然后考虑集合 \(in\) 中选择两个数字,分类讨论:

  • \(|bs|\) 小于等于 \(20\):
    我们暴力枚举两个数字。然后用前缀后缀与快速求出其他数字的与值(记得和\(out\)的与在做一遍 & 运算),然后判断是否有解,时间复杂度 \(O(20\times 20)\)。
  • \(|bs|\) 大于 \(20\):
    那么与值一定为 0,还是一样暴力扫两个值(因为限制只有 20 个,所以复杂度是对的)。

那么这一题基本做完了。写起来当然爽了。
这一题的细节和易错点:

  1. 有一些位,所有数字这一位都是 \(1\),那么将这些位加起来为 \(s\),那么最大公约数就从 \(s+x+1\) 开始枚举。
  2. 本题有重复数字。可以先特判一下选两个重复数字的情况。后面的枚举也要记得考虑这种情况!!!!
#include <bits/stdc++.h>
using namespace std;
#define rep(i,l,r) for (int i = (l); i <= (r); i++)
#define per(i,r,l) for (int i = (r); i >= (l); i--)
#define pb push_back
#define eb emplace_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
#define maxn(a, b) a = max(a, b)
#define minn(a, b) a = min(a, b)
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII;
typedef double db;
const ll mod = 998244353;
mt19937 gen(114514);
ll rp(ll a,ll b) {ll res=1%mod;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}

const int V = (1<<20)-1;

void solve() {
	int n, c, m = 0;
	scanf("%d%d", &n, &c);
	VI a(n);
	for (auto &x : a) {
		scanf("%d", &x);
		maxn(m, x);
	}
	VI cnt(m + 1);
	for (auto x : a) cnt[x]++;
	VI suf(m + 2);
	suf[m + 1] = V;
	rep(i,1,m) suf[i] = cnt[i] ? i : V;
	per(i,m,1) suf[i] &= suf[i + 1];

	auto print = [&](const int &x, const int &y) {
		puts("YES");
		printf("2 %d %d\n", x, y);
		cnt[x]--; cnt[y]--;
		printf("%d", n - 2);
		rep(i,1,m) while (cnt[i]--) printf(" %d", i);
		puts("");
	};

	int pre = V;
	rep(i,1,m) {
		if (cnt[i] > 2) pre &= i;
		if (cnt[i] >= 2 && i > (pre & suf[i + 1]) + c) {
			print(i, i);
			return ;
		}
		if (cnt[i]) pre &= i;
	}

	VI al(21);
	int one = 0, two = 0;
	rep(i,1,m) if (cnt[i]) {
		rep(j,0,20) if (~i>>j&1) al[j] += cnt[i];
	}
	int s = 0;
	rep(j,0,20) {
		if (!al[j]) s |= 1 << j;
		else if (al[j] == 1) {
			one |= 1<<j;
		} else if (al[j] == 2) {
			two |= 1<<j;
		}
	}

	rep(d,s + c + 1,m) {
		VI bs, in(21);
		for (int b = d; b <= m; b += d) {
			if (cnt[b]) {
				bs.pb(b);
				rep(i,0,20) if (~b>>i&1) {
					in[i] += cnt[b];
				} 
			}
		}
		int out = 0;
		rep(i,0,20) if (al[i] == in[i]) {
			out |= 1 << i;
		}
		if (SZ(bs) <= 20) {
			suf = bs; suf.pb(V);
			per(i,SZ(bs)-1,0) suf[i] &= suf[i + 1];
			int l = V;
			rep(i,0,SZ(bs)-1) {
				int mid = V;
				if (cnt[bs[i]] > 1) mid &= bs[i];
				rep(j,i+1,SZ(bs)-1) {
					if (cnt[bs[j]] > 1) mid &= bs[j];
					if ((l & mid & suf[j + 1] & out) + c < d) {
						print(bs[i], bs[j]);
						return ;
					}
					mid &= bs[j];
				}
				l &= bs[i];
			}
		} else {
			rep(i,0,SZ(bs)-1) {
				int vi = V^bs[i];
				if (one & vi) break;
				rep(j,i+1,SZ(bs)-1) {
					int vj = V^bs[j];
					if (one & vj) break;
					if (vi & vj & two) break;
					print(bs[i], bs[j]);
					return ;
				}
			}
		}
	}
	puts("NO");
}

int main() {
	int T;
	scanf("%d", &T);
	while (T--)
		solve();
	return 0;
}

标签:20,数字,int,CF1945,Greater,GCD,bs,ll,define
From: https://www.cnblogs.com/weirdoX/p/18084574

相关文章

  • CodeForces 1945H GCD is Greater
    洛谷传送门CF传送门感觉是这场唯一比较有趣的题?首先明确一点:先手只会选\(2\)个数,因为数多了\(\gcd\)会变小,而且对方的\(\text{and}\)会变大。所以对于某一位,若\(0\)的个数\(\ge3\)那么对方的按位与这一位一定是\(0\)。所以若\(0\)的个数\(\le2\),那么可能会......
  • P5656 【模版】二元一次不定方程(exgcd)
    综合考查exgcd功力的题目。没有整数解当且仅当\(\gcd(a,b)\nmidc\),直接输出-1。用exgcd解方程\(ax+by=\gcd(a,b)\)得到一组特解\(x_0,y_0\)。对原方程变形得到\(a\cdot\dfrac{xc}{\gcd(a,b)}+b\cdot\dfrac{yc}{\gcd(a,b)}=c\),于是有\(ax+by=c\)的一组特解\(x_1=\d......
  • pytorch使用pytorch_wavelets包错误:ValueError: step must be greater than zero 错误
    错误描述在使用pytorch_wavelets包的DWT1DInverse时,发现报错信息如下:Traceback(mostrecentcalllast):File"/work/GDN/test/test_DWT.py",line24,inx_=idwt((YL,YH))File"/opt/conda/lib/python3.6/site-packages/torch/nn/modules/module.py",line550......
  • GCDAsyncSocket_Reference
    原文:https://github.com/robbiehanson/CocoaAsyncSocket/wiki/Reference_GCDAsyncSocketGCDAsyncSocket是基于GrandCentralDispatch构建的TCP套接字网络库。该项目还包含一个基于RunLoop的版本,以及UDP套接字库。CocoaAsyncSocket项目是一个成熟的开源框架,自2003......
  • error: Microsoft Visual C++ 14.0 or greater is required. Get it with "Microsoft
       Defaultingtouserinstallationbecausenormalsite-packagesisnotwriteableCollectingPyQt5-sipUsingcachedPyQt5_sip-12.13.0.tar.gz(123kB)Installingbuilddependencies...doneGettingrequirementstobuildwheel...donePreparing......
  • 3101: *【莫比乌斯反演:练习】gcd(i,j)=k的对数[POI2007]ZAP-Queries
    问题给出\(n,m,k\)(\(1\leqn,m,k\leq10^5\)),求\(\sum\limits_{i=1}^n\sum\limits_{j=1}^m\lbrack\gcd(i,j)=k\rbrack\),即:满足\(1\leqi\leqn\),\(1\leqj\leqm\),且\(\gcd(i,j)=k\)的二元组\((i,j)\)的数量。题解\(\sum\limits_{i=1}......
  • Interval GCD 题解
    题目描述给定一个长度为\(\largen\)的数组\(\largea\),以及\(\largem\)条指令(\(n\leq5\times10^5,m\leq10^5\)),每条指令可能是以下两种之一:“\(\large\operatorname{C\l\r\d}\)”,表示把\(\largea[l],a[l+1],…,a[r]\)都加上\(\larged\)。“\(\large\operatorn......
  • Small GCD
    有两种做法第一种做法:欧拉反演(其实我赛时的时候是想到了欧拉反演的,但是我不太清楚欧拉反演的使用trick)欧拉反演的trick见这篇文章欧拉反演直接用在gcd上还是挺多的,可以想一下\(cnt\)数组怎么求\(cnt\)数组其实是只用记一维的(因为记两维肯定爆炸了)。考虑对于\(d\),如果\(d\)不是......
  • lcm(a,b)=a*b/gcd(a,b)
    求俩组爆int的数据的最小公倍数lcm等价于求这俩个数的最大公因数gcd即lcm(a,b)=a*b/gcd(a,b)求俩组爆int数据的最大公因数可以使用辗转相除法`include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;llgcd(llda,llxiao){inttemp;while(xiao!=0){temp......
  • 使用Docker部署仓库GreaterWMS 仓库管理平台
    参考:https://www.56yhz.com/md/docker_deployment/zh-CN安装Docker不详述配置国内加速器不详述安装docker-compose不详述安装git不详述开始部署拉取代码####拉取代码gitclonehttps://github.com/GreaterWMS/GreaterWMS.git####修改Dockerfile####说明1:如果您......