用两个数字表示第N个数字

时间:2015-05-20 14:03:53

标签: c++ algorithm c++11

编写两个数字表ab并按升序合并在一起,并删除重复项。现在的问题是,在此超级数据中找到nth数字比O(n)复杂度更好。

Limits 

1<=A, B<=1000

1<=N<=1000000000

这是我的意见,但它是O(n),任何人都可以提出更好的复杂性算法吗?谢谢!

#include <iostream>
#include<map>
using namespace std;

long long int min(long long a, long long b){
    if(a<b) return a;
    else return b;
}

long long int get( long long int a,  long long int b,  long long int count) {
    long long int val = 0,i;
    long long int nexta = a;
    long long int nextb = b;
    for ( i = 0; i < count; i++) {
        val = min(nexta, nextb);
        nexta = val < nexta ? nexta : (nexta + a);
        nextb = val < nextb ? nextb : (nextb + b);
    }
    return val;
}


int main() {
    int t;
    cin >> t;

    while(t--){
        long long int a,b,n;
        cin >> a>> b>> n;
        cout << get(a,b,n)<< endl;
    }
    return 0;
}

示例: A = 3,B = 5

表A = 3,6,9,12,15,18等等

表B = 5,10,15,20等等

合并后:3,5,6,9,10,12,15,15,18,20等等

删除重复项:3,5,6,9,10,12,15,18,20等等

对于N = 2,超级表的第二元素是5

1 个答案:

答案 0 :(得分:1)

如果我理解你,arays AB指定如下:

A[i] = a*i
B[i] = b*i

然后您可以通过应用二进制搜索获得至少O(log N)解决方案。

考虑一些价值x。它会超出你的n元素吗?您需要确定联合序列中的元素在x之前的数量。它很容易完成:Ax/a个元素,Bx/b,但是oops ---我们已经计算了两次共同元素。有x/d个公共元素,其中dab的最不常见的乘法,所以让我们减去x/d。因此,如果x/a + x/b - x/d>=n,那么x至少是n元素,否则它就在之前。

现在二进制搜索代码为(伪代码)

l = 0
r = a * n + 1
d = lcm(a,b)
while r-l>1
    m = (r+l)/2
    cnt = m/a + m/b - m/d
    if cnt >= n
        r = m
    else l = m
your answer is r

甚至可以使用O(1)解决方案