zoukankan      html  css  js  c++  java
  • Codeforces 912E

    传送门:http://codeforces.com/contest/912/problem/E

    有整数集上的映射G:S→T。其中S为一个质数集;T为一个整数集:其中,每一个数的所有质因子均为S中的元素。现给定一个n元的质数集S,求T=G(S)中的第k小的整数。

    首先考虑集合T=G(S)的构造:

    设质数集S={pi|i=1,2,...,n},则$T=G(S)={prod_{i=1}^{n}{p_i^{a_i}}|a_i=0,1,2,cdots;i=1,2,cdots,n}$。

    集合T=G(S)可以通过DFS构造,这里用std::vector实现:

    void dfs(int idx, int64_t cur)
    {
        if (idx == s.size()) {
            gs.push_back(cur);
            return;
        }
        if (s[idx] <= inf / cur)
            dfs(idx, cur * s[idx]);
        dfs(idx + 1, cur);
    }

    考虑将S划分成两个集合AB,划分满足:AB=SAB=Ø,则G(A)∩G(B)=Ø。划分的方式可以是按照下标的奇偶性划分,即A={pi|i=1,3,...;i≤n},B={pi|i=2,4,...;i≤n}。于是,占用空间由|G(S)|,降至|G(A)|+|G(B)|。同理,可以通过DFS构造集合G(A)、G(B)。

    order(x)返回x在集合T中的“序号”k:若集合T中第k小的数为tk,则tk≤x<tk+1。可以在O(|G(A)|+|G(B)|)的时间复杂度下实现这个函数。

    之后,在0~inf上查找。采用二分查找法。查找的时间复杂度为O((|G(A)|+|G(B)|)·log inf)。

    参考程序如下:

    #include <bits/stdc++.h>
    using namespace std;
    
    const int64_t inf = (int64_t)1e18;
    vector<int64_t> a[2], g[2];
    
    void dfs(int obj, int idx, int64_t cur)
    {
        if (idx == a[obj].size()) {
            g[obj].push_back(cur);
            return;
        }
        if (a[obj][idx] <= inf / cur)
            dfs(obj, idx, cur * a[obj][idx]);
        dfs(obj, idx + 1, cur);
    }
    
    int order(int64_t x)
    {
        int res = 0;
        int i = g[0].size() - 1, j = 0;
        for (; i >= 0; i--) {
            for (; j < g[1].size() && g[1][j] <= x / g[0][i]; j++);
            res += j;
        }
        return res;
    }
    
    int main(void)
    {
        int n, k;
        scanf("%d", &n);
        for (int i = 0; i < n; i++) {
            int p;
            scanf("%d", &p);
            a[i & 1].push_back(p);
        }
        scanf("%d", &k);
        //generate sequences g-s.
        dfs(0, 0, 1LL);
        sort(g[0].begin(), g[0].end());
        dfs(1, 0, 1LL);
        sort(g[1].begin(), g[1].end());
        //binary search.
        int64_t low = 0LL;
        int64_t high = inf;
        while (low <= high) {
            int64_t mid = (low + high) / 2;
            int ord = order(mid);
            if (ord < k) low = mid + 1;
            else high = mid - 1;
        }
        printf("%I64d
    ", low);
        return 0;
    }
  • 相关阅读:
    解决iOS app集成共享QQ场地,微信的朋友,朋友等功能圈,不能采用苹果公司的审计问题
    沙朗新闻发布系统汇总
    Cocos2d-x示例:单点触摸事件
    【UVA272】TEX Quotes
    Android多线程的研究(8)——Java5于Futrue获取线程返回结果
    Spring Assert主张 (参议院检测工具的方法-主张)
    redmine使用汇总redmine软件工程过程
    IIS7构造Gzip压缩
    PHPthinking官方论坛
    javaweb学习总结(十一)——使用Cookie进行会话管理
  • 原文地址:https://www.cnblogs.com/siuginhung/p/8232064.html
Copyright © 2011-2022 走看看