小于O(n ^ 2)复杂度的两个数组的互质对数

时间:2018-12-28 10:33:19

标签: algorithm time-complexity

我遇到了一个挑战。 有两个数组A和B,它们的大小均为N,我们需要返回对数(A [i],B [j]),其中gcd(A[i],B[j])==1A[i] != B[j]。 我只能想到暴力测试方法在几个测试用例中都超过了时间限制。

for(int i=0; i<n; i++) {
    for(int j=0; j<n; j++) {
        if(__gcd(a[i],b[j])==1) {
             printf("%d %d\n", a[i], b[j]);
        }
    }
}

您能建议省时的算法来解决这个问题吗?

编辑:无法共享问题链接,因为这是来自招聘方面的挑战。我记得添加了约束和输入/输出格式。

输入-

  • 第一行将包含N,即两个数组中存在的元素数。
  • 第二行将包含N个以空格分隔的整数,即数组A的元素。
  • 第三行将包含N个以空格分隔的整数,即数组B的元素。

输出-

  • 根据条件对A [i],A [j]的计数。

约束-

  • 1 <= N <= 10 ^ 5
  • 1

2 个答案:

答案 0 :(得分:3)

第一步是使用Eratosthenes sieve计算不超过sqrt(10^9)的素数。然后,可以使用此筛子快速查找小于10^9的任意数量的所有素因数(请参见下面的代码示例中的getPrimeFactors(...)函数)。

接下来,对于每个具有主因子A[i]的{​​{1}},我们计算所有可能的子产品p0, p1, ..., pk-X并将其计入映射p0, p1, p0p1, p2, p0p2, p1p2, p0p1p2, p3, p0p3, ..., p0p1p2...pk中。实际上,映射cntp[X]告诉我们元素cntp[X]A[i]整除的数量,其中X是质数乘以0或1的幂的乘积。例如,对于数字X,主要因素是A[i] = 12。我们将计算2, 3cntp[2]++cntp[3]++

最后,对于每个具有主因子cntp[6]++的{​​{1}},我们再次计算所有可能的子产品B[j],然后使用Inclusion-exclusion principle来计算所有非互质对{ {1}}(即与p0, p1, ..., pk共享至少一个素数的X个数)。然后从对总数中减去数字C_j-A[i]得到最终答案。

注意:“包含-排除”原理如下:

B[j]

并考虑到这样一个事实,即在C_j和{{ 1}}。

这是该算法的可能的C ++实现,其产生的结果与OP的朴素O(n ^ 2)算法相同:

N*N

Live example

我无法通过分析来估计复杂度,但这是我的笔记本电脑上针对不同C_j = (cntp[p0] + cntp[p1] + ... + cntp[pk]) - (cntp[p0p1] + cntp[p0p2] + ... + cntp[pk-1pk]) + (cntp[p0p1p2] + cntp[p0p1p3] + ... + cntp[pk-2pk-1pk]) - ... 以及统一随机cntp[X]cntp[Y]的一些分析结果:

A[i]

为进行比较,O(n ^ 2)方法采用:

X

答案 1 :(得分:0)

Python 实现:

    import math
    from collections import defaultdict

    def sieve(MAXN):
        spf = [0 for i in range(MAXN)]
        spf[1] = 1
        for i in range(2, MAXN):
            spf[i] = i
        for i in range(4, MAXN, 2):
            spf[i] = 2
        for i in range(3, math.ceil(math.sqrt(MAXN))):
            if (spf[i] == i):
                for j in range(i * i, MAXN, i):
                    if (spf[j] == j):
                        spf[j] = i
        return(spf)

    def getFactorization(x,spf):
        ret = list()
        while (x != 1):
            ret.append(spf[x])
            x = x // spf[x]
        return(list(set(ret)))

    def coprime_pairs(N,A,B):
        MAXN=max(max(A),max(B))+1
        spf=sieve(MAXN)
        cntp=defaultdict(int)
        for i in range(N):
            f=getFactorization(A[i],spf)
            x=[[0,1]]
            for p in f:
                k=len(x)
                for i in range(k):
                    nn=x[i][0]+1
                    pp=x[i][1]*p
                    cntp[pp]+=1
                    x.append([nn,pp])
        cnt=0
        for i in range(N):
            f=getFactorization(B[i],spf)
            x=[[0,1]]
            for p in f:
                k=len(x)
                for i in range(k):
                    nn=x[i][0]+1
                    pp=x[i][1]*p
                    x.append([nn,pp])
                    if(nn%2==1):
                        cnt+=cntp[pp]
                    else:
                        cnt-=cntp[pp]
        return(N*N-cnt)

    import random
    N=10001
    A=[random.randint(1,N) for _ in range(N)]
    B=[random.randint(1,N) for _ in range(N)]
    print(coprime_pairs(N,A,B))