CF912E Prime Gift(Meeting In The Middle+Two pointers)

原题

挂个链接CodeForces

题目大意:给定k个质数,求出约数中只有由这几个数组合一下(可以多次用一个数)的第k个值

Solution

分析:

我们看到n是16,然后如果爆搜n/2是可以过的.所以考虑Meeting In The Middle

他让我们求第k个数,理所应当地想到二分答案.

然后我们先把所有的组合求出来,然后二分答案判断就好了.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<iostream>
#include<queue>
#include<algorithm>
#define ll long long
#define re register
using namespace std;
inline int gi(){
  int sum=0,f=1;char ch=getchar();
  while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
  return f*sum;
}
inline ll gl(){
  ll sum=0,f=1;char ch=getchar();
  while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
  return f*sum;
}
int n,p[20],t1,t2;
ll s1[5000010],s2[5000010],k;
void dfs1(int x,ll s){
  if(x>n){s1[++t1]=s;return;}
  for(ll w=1;;w*=p[x]){dfs1(x+2,s*w);if(1e18/p[x]<w*s)break;}
}
void dfs2(int x,ll s){
  if(x>n){s2[++t2]=s;return;}
  for(ll w=1;;w*=p[x]){dfs2(x+2,s*w);if(1e18/p[x]<w*s)break;}
}
int main(){
  n=gi();
  for(re int i=1;i<=n;i++)p[i]=gi();
  sort(p+1,p+n+1);
  dfs1(1,1);dfs2(2,1);
  sort(s1+1,s1+t1+1);sort(s2+1,s2+t2+1);
  k=gi();
  ll l=0,r=1e18,ans;
  while(l<=r){
    ll mid=(l+r)>>1,tot=0;
    for(re int i=1,p=t2;i<=t1;i++,tot+=p)
      while(p && mid/s1[i]<s2[p])p--;
    if(tot<k)l=mid+1;
    else{ans=mid;r=mid-1;}
  }
  printf("%lld\n",ans);
  return 0;
}

原文地址:https://www.cnblogs.com/cjgjh/p/9769489.html

时间: 2024-10-08 21:05:29

CF912E Prime Gift(Meeting In The Middle+Two pointers)的相关文章

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

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

CF912E Prime Gift 数学

Opposite to Grisha's nice behavior, Oleg, though he has an entire year at his disposal, didn't manage to learn how to solve number theory problems in the past year. That's why instead of Ded Moroz he was visited by his teammate Andrew, who solemnly p

POJ 3126 Prime Path (bfs+欧拉线性素数筛)

Description The ministers of the cabinet were quite upset by the message from the Chief of Security stating that they would all have to change the four-digit room numbers on their offices. - It is a matter of security to change such things every now

CodeForces - 76A:Gift (最小生成树 解决单调性问题是思想)

题意:给定N点M边的无向连通图,每条边有两个权值(g,s). 给定G,S. 让你给出一组(g0,s0)使得图中仅留下g<=g0, s<=s0的边之后,依然连通,并求Gg0+Ss0的最小值. n<=200,m<=50000. 思路:枚举g0,求最小的s0,满足生成MST. 把边按g排序,一条边一条边的加入,然后在加入边的集合里面找出最小的s.但是每次排序复杂度过高,而且边数也过多,(LCT做也行吧,就不需要考虑这么多). 我们去优化暴力的做法.假设新加入一条边,显然最多改变一条边,那

HDU 3823 Prime Friend(线性欧拉筛+打表)

Besides the ordinary Boy Friend and Girl Friend, here we define a more academic kind of friend: Prime Friend. We call a nonnegative integer A is the integer B’s Prime Friend when the sum of A and B is a prime. So an integer has many prime friends, fo

HDU 2136 Largest prime factor (素数打表。。。)

题意:给你一个数,让你求它的最大因子在素数表的位置. 析:看起来挺简单的题,可是我却WA了一晚上,后来终于明白了,这个第一层循环不是到平方根, 这个题和判断素数不一样,只要明白了这一点,就很简单了. 代码如下: #include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <vector> #include <cstring>

912E - Prime Gift

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

【Best Coder】#29 B GTY&#39;s birthday gift(快速幂|mod的时候记得负!)

题目大意:查看相关场次即可看到. 思路:推公式的题目,可以用快速幂加公式快速解决,也可以用二进制拆分运算的方法加快速度. 需要注意的一点在于:今后在mod之后有涉及到运算的都要加上一个mod之后再mod,或者统一都加一个mod 顺便复习一下二进制拆分的方法!! 二进制拆分的做法AC代码: #define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<algorithm> #include<cstdio> usin

hdu 5171 GTY&#39;s birthday gift(数学,矩阵快速幂)

题意: 开始时集合中有n个数. 现在要进行k次操作. 每次操作:从集合中挑最大的两个数a,b进行相加,得到的数添加进集合中. 以此反复k次. 问最后集合中所有数的和是多少. (2≤n≤100000,1≤k≤1000000000) 思路: 写出来发现是要求Fibonaci的前n个数的和. Fibonaci是用矩阵快速幂求的,这个也可以. [Sn,Fn,Fn-1]=[某个矩阵]*[Sn-1,Fn-1,Fn-2] [S2,F2,F1]=[2,1,1] 然后写,,, 这个代码有些繁琐,应该把矩阵操作单独