Prime Gift CodeForces - 912E (中途相遇)

链接

大意:求素因子只含给定素数的第k大数

先二分答案转为判定x是第几大, 然后分两块合并即可, 按奇偶分块可以优化一下常数

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define pb push_back

using namespace std;
typedef long long ll;

const int N = 2e5+10;
int a[N], b[N], f[N], n, m;
ll k;
vector<ll> s[2];

ll calc(ll x) {
	ll ans = 0;
	int now = 0;
	PER(i,0,s[0].size()-1) {
		while (now<s[1].size()&&s[1][now]<=x/s[0][i]) ++now;
		ans += now;
	}
	return ans;
}

void dfs(int d, int cur, ll now) {
	s[d].pb(now);
	REP(i,cur,*f) if (now<=1e18/f[i]) dfs(d,i,now*f[i]);
}

int main() {
	scanf("%d", &n);
	REP(i,1,n) scanf("%d", a+i);
	sort(a+1,a+1+n);
	scanf("%lld", &k);
	REP(i,1,n) if (i&1) f[++*f] = a[i];
	dfs(0,1,1), *f = 0;
	REP(i,1,n) if (i&1^1) f[++*f] = a[i];
	dfs(1,1,1);
	sort(s[0].begin(),s[0].end());
	sort(s[1].begin(),s[1].end());
	ll l = 1, r = 1e18, ans;
	while (l<=r) {
		int mid = (l+r)/2;
		if (calc(mid)>=k) ans = mid, r = mid-1;
		else l = mid+1;
	}
	printf("%lld\n", ans);
}

原文地址:https://www.cnblogs.com/uid001/p/10409960.html

时间: 2024-10-06 05:19:59

Prime Gift CodeForces - 912E (中途相遇)的相关文章

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

题目链接 Prime Gift 题意  给定一个素数集合,求第k小的数,满足这个数的所有质因子集合为给定的集合的子集. 保证答案不超过$10^{18}$ 考虑二分答案. 根据折半的思想,首先我们把这个集合的数分成两组. 然后分别生成这两组质数所能表示出的正整数的集合. 然后把这个集合sort一下,我们得到了两个有序的数列. 在计算小于等于某个数$x$的符合题目条件的数的时候,我们枚举第一个集合中的数, 用双指针定位和当前枚举到的数乘积恰好小于等于$x$的位置. 然后累加. 这里有一个细节,我们要

codeforces 525 E Anya and Cubes 中途相遇法

codeforces 525 E Anya and Cubes 中途相遇法 题意: 给出n个数a1,a2,...,an,要求从中选出一些数,可以把其中最多k个变成它自己的阶乘,然后选出的数求和,问最后和等于s的选法有多少种. 限制: 1 <= n <= 25; 0 <= k <= n; 1<= s <= 1e16; 1 <= ai <= 1e9 思路: 一般数据量20~30都会考虑中途相遇法,就是折半暴力. ps:用三进制暴力会比直接深搜多一个常数10,因为

912E - Prime Gift

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

Codeforces Round #297 (Div. 2) E题. Anya and Cubes (中途相遇法)

题目地址:Anya and Cubes 比赛的时候居然没想起中途相遇法...这题也是属于想起来就很简单系列. 中途相遇法也叫折半搜索.就是处理前一半,把结果储存起来,再处理后一半,然后匹配前一半存储的结果. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib

Codeforces 31E TV Game 中途相遇法 状压dp

题目链接:点击打开链接 题意: 给定2*n长的数字. 把这个数字拆成2个长度为n的数字,且相对位置不变.使得拆后得到的2个数字的和最大. 输出一个方案. 显然是中途相遇法,先计算左半段,再计算右半段 分别状压左半段和右半段,注意左半段状压后要在末尾补上0. 代码估计哪里有小越界==,数组开大了一点才过..具体就不查了. #include<iostream> #include<stdio.h> #include<string.h> #include<string&g

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

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

【中途相遇法】【STL】BAPC2014 K Key to Knowledge

题目链接: http://codeforces.com/gym/100526 http://acm.hunnu.edu.cn/online/?action=problem&type=show&id=11674&courseid=0 题目大意: N个学生M道题(1<=N<=12,1<=M<=30),每道题只有正误两种选项(0 1),每个学生的答题情况和正确题数已知,求标准答案可能有多少种. 如果标准答案只有一种则输出标准答案,否则输出解的个数. 题目思路: [

uva 6757 Cup of Cowards(中途相遇法,貌似)

uva 6757 Cup of CowardsCup of Cowards (CoC) is a role playing game that has 5 di?erent characters (Mage, Tank, Fighter,Assassin and Marksman). A team consists of 5 players (one from each kind) and the goal is to kill amonster with L life points. The

uva1152 - 4 Values whose Sum is 0(枚举,中途相遇法)

用中途相遇法的思想来解题.分别枚举两边,和直接暴力枚举四个数组比可以降低时间复杂度.可是我不会写...看了紫书作者刘汝佳老师的代码,真是太美了!简单明了,就像看吕钦下的棋一样.我就模仿的写了一下: #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> #include<set>