首页 > 其他分享 >CodeForces 1945H GCD is Greater

CodeForces 1945H GCD is Greater

时间:2024-03-19 20:23:15浏览次数:34  
标签:typedef Greater int 1945H CodeForces long maxn 按位 define

洛谷传送门

CF 传送门

感觉是这场唯一比较有趣的题?

首先明确一点:先手只会选 \(2\) 个数,因为数多了 \(\gcd\) 会变小,而且对方的 \(\text{and}\) 会变大。

所以对于某一位,若 \(0\) 的个数 \(\ge 3\) 那么对方的按位与这一位一定是 \(0\)。

所以若 \(0\) 的个数 \(\le 2\),那么可能会选这一位是 \(0\) 的,导致对方的按位与这一位是 \(1\)。把它们加入一个集合 \(S\) 中。

对每一位做这一步后 \(S\) 的大小为 \(O(\log V)\)。枚举 \(S\) 中的每个元素,再 \(O(n)\) 枚举另外一个选什么,\(O(\log V)\) check 一下即可(\(O(\log V)\) 是因为要算 \(\gcd\))。

令 \(T = \{1, 2, \ldots, n\} \setminus S\)。此时还没有考虑选 \(T\) 中的数。但是因为选 \(T\) 中的任意两个数,剩下的数的按位与都等于原序列的按位与,所以我们只可能选 \(T\) 中两两 \(\gcd\) 最大的两个数,设它们为 \(a_x, a_y\)。特殊考虑一下它们即可。

总时间复杂度 \(O(n \log^2 V)\)。

code
// Problem: H. GCD is Greater
// Contest: Codeforces - Codeforces Round 935 (Div. 3)
// URL: https://codeforces.com/contest/1945/problem/H
// Memory Limit: 512 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 400100;
const int N = 400000;
const int logn = 21;

int n, m, a[maxn], K, b[maxn], f[logn][maxn];
bool vis[maxn];
vector<int> di[maxn];

inline void init() {
	for (int i = 1; i <= N; ++i) {
		for (int j = i; j <= N; j += i) {
			di[j].pb(i);
		}
	}
}

inline int qand(int l, int r) {
	if (l > r) {
		return -1;
	}
	int k = __lg(r - l + 1);
	return (f[k][l] & f[k][r - (1 << k) + 1]);
}

inline int query(int x, int y) {
	if (x > y) {
		swap(x, y);
	}
	return qand(1, x - 1) & qand(x + 1, y - 1) & qand(y + 1, n);
}

void solve() {
	scanf("%d%d", &n, &m);
	K = 0;
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]);
		K = max(K, a[i]);
		vis[i] = 0;
		f[0][i] = a[i];
	}
	for (int j = 1; (1 << j) <= n; ++j) {
		for (int i = 1; i + (1 << j) - 1 <= n; ++i) {
			f[j][i] = (f[j - 1][i] & f[j - 1][i + (1 << (j - 1))]);
		}
	}
	for (int i = 1; i <= K; ++i) {
		b[i] = 0;
	}
	vector<int> S;
	for (int i = 18; ~i; --i) {
		vector<int> T;
		for (int j = 1; j <= n; ++j) {
			if ((~a[j]) & (1 << i)) {
				T.pb(j);
			}
		}
		if ((int)T.size() <= 2) {
			for (int i : T) {
				S.pb(i);
				vis[i] = 1;
			}
		}
	}
	for (int i = 1; i <= n; ++i) {
		if (!vis[i]) {
			for (int j : di[a[i]]) {
				++b[j];
			}
		}
	}
	for (int i = K; i; --i) {
		if (b[i] >= 2) {
			vector<int> T;
			for (int j = 1; j <= n && (int)T.size() < 2; ++j) {
				if (a[j] % i == 0 && !vis[j]) {
					T.pb(j);
				}
			}
			int x = __gcd(a[T[0]], a[T[1]]), y = query(T[0], T[1]);
			if (x > y + m) {
				printf("YES\n2 %d %d\n%d ", a[T[0]], a[T[1]], n - 2);
				for (int k = 1; k <= n; ++k) {
					if (k == T[0] || k == T[1]) {
						continue;
					}
					printf("%d ", a[k]);
				}
				putchar('\n');
				return;
			}
			break;
		}
	}
	sort(S.begin(), S.end());
	S.erase(unique(S.begin(), S.end()), S.end());
	for (int i : S) {
		for (int j = 1; j <= n; ++j) {
			if (i == j) {
				continue;
			}
			int x = __gcd(a[i], a[j]), y = query(i, j);
			if (x > y + m) {
				printf("YES\n2 %d %d\n%d ", a[i], a[j], n - 2);
				for (int k = 1; k <= n; ++k) {
					if (i == k || j == k) {
						continue;
					}
					printf("%d ", a[k]);
				}
				putchar('\n');
				return;
			}
		}
	}
	puts("NO");
}

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

标签:typedef,Greater,int,1945H,CodeForces,long,maxn,按位,define
From: https://www.cnblogs.com/zltzlt-blog/p/18083873

相关文章

  • Codeforces Round 923 (Div. 3) D. Find the Different Ones!
    写点简单的思维题https://codeforces.com/problemset/problem/1927/D思路:用两个数组,一个存储原始数据,一个用nex存该位置第一次不一样的下标#include<iostream>#include<vector>#include<algorithm>#include<math.h>#include<sstream>#include<string>#include<str......
  • 1948.Educational Codeforces Round 163 - sol
    202403补题效率低下。场上发挥并不是很好,A~E都是简单的,而场上没有去推F的式子,只是找了找规律,然后发现是一个不可做的东西就下播了。如果直接推式子就会很快地做出来,还是非常可惜。A.SpecialCharactersYouaregivenaninteger\(n\).Yourtaskistobuildast......
  • Codeforces Round 920 (Div. 3)----->E. Eat the Chip
    一,思路:1.这是一道博弈论的题目(两个人都绝顶聪明,所以每个人都会按最优方案进行)。这题你会发现,两个人从一开始就已经确定了结局。2.如假如他们俩的棋子在竖直方向上距离相差的值是偶数,那么一定就两个结果Alice赢或者平局,反之奇数则是Bob赢或者平局(仔细分析一下就能得知)。3.所......
  • Codeforces Round 918 (Div. 4)----->E. Romantic Glasses
    一,思路:这题是一道前缀和的扩展题。题目要我们求是否有一个区间内的奇偶之和是否相等,我们可以对数组重新赋值,奇数位赋值为负数,偶数位不变。这样我们后面求前缀和,只要看有没有一段区间和为零的。二,代码:#include<iostream>#include<cstring>#include<algorithm>#include<vec......
  • CodeForces 1943D2 Counting Is Fun (Hard Version)
    洛谷传送门CF传送门被自己的赛时智障操作气笑了。谁告诉你容斥钦定了几个要记到状态里面的。。。/tuu显然先找“好数组”的充要条件。对原数组\(a\)差分,设\(b_i=a_i-a_{i-1}\)。那么一次可以选择一对\((i,j)\)满足\(i\lej-2\),然后给\(b_i\)减\(1\),给\(b_......
  • Codeforces Round 933 G. Rudolf and Subway
    原题链接:Problem-G-Codeforces思路:根据题意可知相同颜色的边一定是联通的,那么就可以设置虚点,例如1-2,2-3,3-4边的颜色都是相同的,那么就可以设置一个特殊的点例如设置为10,那么这三条边就可以改成1-10,10-2,2-10,10-3,3-10,10-4,从点到虚点需要1的代价,但是从虚点到其他点不需要代价,......
  • CodeForces 1943C Tree Compass
    洛谷传送门CF传送门发现对于一条链,一次操作最多能染黑这条链上的\(2\)个点。所以我们把直径拎出来,设直径长度为\(d\)。考虑一条长度为\(d\)的链至少要多少次能全染黑。若\(d\)为奇数,显然从直径中点\(u\)开始做\((u,0),(u,1),\ldots,(u,\frac{d-1}{2})\)......
  • Codeforces Round 933 Rudolf and k Bridges
    原题链接:Problem-E-Codeforces题目大意:给一个行为n列为m的河流二维数组,数字代表河流的深度。题目要求连续建造k座桥,桥的定义是从第一列到第m列,每隔d需要按照支架,安装支架的代价是深度+1。问安装最少需要多少代价?思路:单调队列优化dp,dp数组只需要一维,dp[i]的含义是从1到i建......
  • codeforces 1931E
    题目链接简介:对一些数字,余念安可以反转一个数字,齐夏将两个数字首尾相连变为一个数字。每个人都采取最优策略。名单上只剩下一个号码。如果该整数不小于 10的m次方,则齐夏获胜。否则余念安就赢了。分析:博弈论问题,结局已经确定,可知变成了位数个数之争,齐夏要通过合并数字使得......
  • Codeforces Round 934 (Div. 1)
    Preface真是一场酣畅淋漓的掉分啊,一场回到解放前了属于是这把虽然有不可抗力的原因(电脑半路蓝屏了),但不知道为什么状态就特别差A刚开始没清空干净WA了2发后就心态崩了,然后加上头疼难耐B题也没看出关键trick直接写了个不仅错还巨难写的东西不过yysy这场Guess的成分是否有点太高......