我遇到了一个挑战。
有两个数组A和B,它们的大小均为N,我们需要返回对数(A [i],B [j]),其中gcd(A[i],B[j])==1
和A[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]);
}
}
}
您能建议省时的算法来解决这个问题吗?
编辑:无法共享问题链接,因为这是来自招聘方面的挑战。我记得添加了约束和输入/输出格式。
输入-
输出-
约束-
答案 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, 3
,cntp[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
我无法通过分析来估计复杂度,但这是我的笔记本电脑上针对不同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))