Codeforces H. Prime Gift (binary enumeration half)

Subject description:

Prime Gift
time limit per test
3.5 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

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 presented him with a set of n distinct prime numbers alongside with a simple task: Oleg is to find the k-th smallest integer, such that all its prime divisors are in this set.
Input

The first line contains a single integer n (1 ≤ n ≤ 16).

The next line lists n distinct prime numbers p1, p2, ..., pn (2 ≤ pi ≤ 100) in ascending order.

The last line gives a single integer k (1 ≤ k). It is guaranteed that the k-th smallest integer such that all its prime divisors are in this set does not exceed 1018.
Output

Print a single line featuring the k-th smallest integer. It's guaranteed that the answer doesn't exceed 1018.
Examples
input

3
2 3 5
7

output

8

input

5
3 7 11 13 31
17

output

93

Note

The list of numbers with all prime divisors inside {2, 3, 5} begins as follows:

(1, 2, 3, 4, 5, 6, 8, ...)

The seventh number in this list (1-indexed) is eight.

Ideas:

At first completely ignorant force like -> This o ((⊙﹏⊙)) o what we do not, what ideas did not. What is the title, filled with up to give you a set of primes S sixteen calculate the k number, so that all prime factors of the number in this set. The first idea is violent enumerated, enumerating constructed from these numbers is less than or equal to all \ (10 ^ {18} \) number. The first step we can construct ye will not (but I will not). Only later did know that you can set G with construction dfs violence, like this:

void dfs(int l,int r,long long val)//l,r指给的素数集合区间左右端点
{
    num.push_back(val);//num存构造的数
    for(int i = l;i<=r;i++)
    {
        if(val<=INF/a[i])//INF就是10^18
        {
            dfs(i,r,val*[i],id);//不断选择素因子相乘
        }
    }
}
dfs(1,a.size()-1,1);

You can also so

void dfs(int idx, int64_t cur)
{
    if (idx == s.size()) {//s是存的素因子的集合
        gs.push_back(cur);//gs是构造出的数
        return;
    }
    if (s[idx] <= inf / cur)
        dfs(idx, cur * s[idx]);
    dfs(idx + 1, cur);
}

So set G constructed well, but certainly timeout. So consider binary, how fold. The odd prime factor set of the standard elements of a set of points referred to as S1, and a sub-set of the even index referred to as S2, then were constructed G1, G2, doing so can reduce the enumerated range (regardless if it will enumerate a very large range). and then? We find from 1 to INF dichotomous number x, such that x k is the number of prime factors set in the configuration, to find x title claims.

Then how do we determine if a number is the first of several original number set G of it? You know, the newly constructed G1, G2 constructed only half of the original S, leaving a shortfall of two collections "take up" to get the number. Example, S = {2,3,5}, S1 = {2,5}, S2 = {3}, G1 = {2,4,5,8,10, ...}, G2 = {3,9, 27,81, ...}. But the {6,18, ...}, and so there are two numbers "multiplied" by the set. That is also how do you know the number of x number of G is the first of several it? Here used ingenious idea is to set the maximum row elements from a set of G1 G1 begins the enumeration sequence after a good [I], see set G2, the second plurality can be less than a few equal \ (\ frac {x} { G1 [I]} \) , which is actually an operation on the two sets of "multiplication" manifested, that is, look at the front decimal number to the number x is equal to x, as said earlier, the G1 is G "multiply" the result of G2. So finally obtained is in a position x in G itself.

注意的是一个技巧,在看G2中有多少个数小于等于\(\frac{x}{G1[i]}\)时由于G1[i]是从小到大的,那么上一次判断的终止G2[j]一定小于\(\frac{x}{G1[i]}\),因此G2不必每次都从0开始判断,直接接着上一次判断的结果继续累计就可以了。

还有就是二分答案的细节返回l(左端点),当然不同的写法返回的不一定是l。

代码:

#include <iostream>
#include <algorithm>
#include <vector>
#define max_n 20
#define INF  1e18
using namespace std;
int n;
int k;
int fac[max_n];
vector<long long> num[2];
vector<int> a[2];
void dfs(int l,int r,long long val,int id)
{
    num[id].push_back(val);
    for(int i = l;i<=r;i++)
    {
        if(val<=INF/a[id][i])
        {
            dfs(i,r,val*a[id][i],id);
        }
    }
}
int check(long long x)
{
    long long res = 0;
    long long j = 0;
    for(int i = num[0].size()-1;i>=0;i--)
    {
        while(j<num[1].size()&&num[1][j]<=x/num[0][i]) j++;
        res += j;
    }
    return res;
}
int main()
{
    cin >> n;
    for(int i = 0;i<n;i++)
    {
        int tmp;
        cin >> tmp;
        a[i&1].push_back(tmp);
    }
    cin >> k;
    dfs(0,a[0].size()-1,1,0);
    sort(num[0].begin(),num[0].end());
    dfs(0,a[1].size()-1,1,1);
    sort(num[1].begin(),num[1].end());
    /*for(int i = 0;i<num[0].size();i++)
    {
        cout << num[0][i] << " ";
    }
    cout << endl;
    for(int i = 0;i<num[1].size();i++)
    {
        cout << num[1][i] << " ";
    }
    cout << endl;*/
    long long l = 0;
    long long r = INF;
    long long mid;
    while(l<=r)
    {
        mid = (l+r)>>1;
        long long ord = check(mid);
        if(ord<k)
        {
            l = mid+1;
        }
        else
        {
            r = mid-1;
        }
    }
    cout << l << endl;
    return 0;
}

参考文章:

Wisdom+.+,912E - Prime Gift,https://www.cnblogs.com/widsom/p/8352859.html

SiuGinHung,Codeforces 912E - Prime Gift,https://www.cnblogs.com/siuginhung/p/8232064.html

Guess you like

Origin www.cnblogs.com/zhanhonhao/p/11334406.html