Codeforces 912E Prime Gift(预处理 + 双指针 + 二分答案)

题目链接 Prime Gift

题意  给定一个素数集合,求第k小的数,满足这个数的所有质因子集合为给定的集合的子集。

保证答案不超过$10^{18}$

考虑二分答案。

根据折半的思想,首先我们把这个集合的数分成两组。

然后分别生成这两组质数所能表示出的正整数的集合。

然后把这个集合sort一下,我们得到了两个有序的数列。

在计算小于等于某个数$x$的符合题目条件的数的时候,我们枚举第一个集合中的数,

用双指针定位和当前枚举到的数乘积恰好小于等于$x$的位置。

然后累加。

这里有一个细节,我们要保证两个正整数的集合的大小要尽可能接近。

所以分组方式要稍微讲究一下,

我这里先对整个数列sort,再根据位置的奇偶性把整个数列分成两组。

这道题的极限数据的集合应该是前$16$小的质数……

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

typedef long long LL;

const int N = 63;

int n;
int cnt;
LL a[N], c[N], k, l, r;
vector <LL> s[2];

void dfs(int i, int x, LL now){
	s[i].push_back(now);
	rep(j, x, cnt) if (1e18 / c[j] >= now) dfs(i, j, now * c[j]);
}

LL solve(LL x){
	int j = 0;
	LL ret = 0;
	dec(i, s[0].size() - 1, 0){
		while (j < s[1].size() && s[1][j] <= x / s[0][i]) ++j;
		ret += j;
	}
	return ret;
}

int main(){

	scanf("%d", &n);
	rep(i, 1, n) scanf("%lld", a + i);
	sort(a + 1, a + n + 1);
	scanf("%lld", &k);

	cnt = 0;
	rep(i, 1, n) if (i & 1) c[++cnt] = a[i];
	dfs(0, 1, 1);

	cnt = 0;
	rep(i, 1, n) if (!(i & 1)) c[++cnt] = a[i];
	dfs(1, 1, 1);

	sort(s[0].begin(), s[0].end());
	sort(s[1].begin(), s[1].end());

	l = 1, r = 1e18;
	while (l + 1 < r){
		LL mid = (l + r) / 2;
		if (solve(mid) >= k) r = mid;
		else l = mid + 1;
	}

	if (solve(l) >= k) printf("%lld\n", l);
	else printf("%lld\n", r);
	return 0;
}

  

原文地址:https://www.cnblogs.com/cxhscst2/p/8215646.html

时间: 2024-10-17 03:31:02

Codeforces 912E Prime Gift(预处理 + 双指针 + 二分答案)的相关文章

912E - Prime Gift

912E - Prime Gift 思路: 折半枚举+二分check 将素数分成两个集合(最好按奇偶位置来,保证两集合个数相近),这样每个集合枚举出来的小于1e18的积个数小于1e6. 然后二分答案,check时枚举其中一个集合,然后找到另外一个集合小于mid/该元素的元素有多少个,这里用到一个双指针的技巧将复杂度降到O(n):一个集合从大到小枚举,那么mid/该元素就会逐渐变大,那么直接从上次找到的位置往后找就可以了,因为答案肯定在后面. 代码: #include<bits/stdc++.h>

Codeforces Round #256 (Div. 2)D 二分答案

D. Multiplication Table time limit per test 1 second memory limit per test 256 megabytes input standard input output standard output Bizon the Champion isn't just charming, he also is very smart. While some of us were learning the multiplication tabl

Codeforces Round #262 (Div. 2)C(二分答案,延迟标记)

这是最大化最小值的一类问题,这类问题通常用二分法枚举答案就行了. 二分答案时,先确定答案肯定在哪个区间内.然后二分判断,关键在于怎么判断每次枚举的这个答案行不行. 我是用a[i]数组表示初始时花的高度,b[i]表示要达到当前枚举的答案(即mid的值)需要这朵花再涨多少.这两个数组很好算,关键是一次浇连续的w朵花,如何更新区间(暴力的O(n2)的去更新就超时了)?可以用线段树,但是这道题没有涉及区间查询,就是在一个数组上更新区间,用线段树未免小题大做.那么其实这种更新就用延迟标记的思想(懒操作)就

Codeforces 912 E.Prime Gift (折半枚举、二分)

题目链接:Prime Gift 题意: 给出了n(1<=n<=16)个互不相同的质数pi(2<=pi<=100),现在要求第k大个约数全在所给质数集的数.(保证这个数不超过1e18) 题解: 如果暴力dfs的话肯定超时间,其实给的n数据范围最大是16是一个很奇妙的数(一般折半枚举基本上是这样的数据范围@.@-).所以想到折半枚举,把所有的质数分成两份求出每份中所有小于1e18的满足条件的数.然后二分答案,写cheak函数时遍历第一个集合,对第二个集合二分(折半枚举基本上这个套路).

Educational Codeforces Round 21 Problem F (Codeforces 808F) - 最小割 - 二分答案

Digital collectible card games have become very popular recently. So Vova decided to try one of these. Vova has n cards in his collection. Each of these cards is characterised by its power pi, magic number ci and level li. Vova wants to build a deck

Codeforces 772A Voltage Keepsake - 二分答案

You have n devices that you want to use simultaneously. The i-th device uses ai units of power per second. This usage is continuous. That is, in λ seconds, the device will use λ·ai units of power. The i-th device currently has bi units of power store

Codeforces 700A As Fast As Possible(二分答案)

[题目链接] http://codeforces.com/problemset/problem/700/A [题目大意] 有一辆限载k人速度为v2的车,n个步行速度均为v1的人要通过一段长度为l的距离,每个人只能上车一次,车可以来回走,问所有人到达目的地所需要的最短时间是多少 [题解] 因为车可以载k个人,所以,我们把人k个为一组分成(n+k-1)/k组,记为p吗,设需要的最短时间为t,每个人在车上待的时间为t2,那么可以列方程v1*(t-t2)+v2*t2=l,我们可以发现t2可以用t来表示,

Codeforces Round #425 (Div. 2) Problem C (Codeforces 832C) Strange Radiation - 二分答案 - 数论

n people are standing on a coordinate axis in points with positive integer coordinates strictly less than 106. For each person we know in which direction (left or right) he is facing, and his maximum speed. You can put a bomb in some point with non-n

Codeforces Round #417 (Div. 2) C. Sagheer and Nubian Market 二分答案 +排序

Codeforces Round #417 (Div. 2) C. Sagheer and Nubian Market 二分答案 +排序 题意 有 a[ i ] 个数 要求选最多的数 使其和不超过 S ,且在此情况下,和最小选最多数情况下 和最小 且 每个数有加成 如果选了 k个数 那么加成后 就是 a[ i ] + k*i ; 题解 二分mid 表示选了个数 加成一下,将加成以后结果排序一下 , 若前 mid数 和大于 s 则此方案不可行 PS 要用 long long ..... 还有 co