查找一组数字的GCD?

时间:2015-10-11 11:39:22

标签: c++ algorithm

所以,我在接受采访时被问到这个问题。给定一组数字(不一定是不同的),我必须找到给定数字组的所有可能子集的GCD的乘法。

我告诉面试官的方法是:

1. Recursively generate all possible subsets of the given set.
2a. For a particular subset of the given set:
2b. Find GCD of that subset using the Euclid's Algorithm.
3. Multiply it in the answer being obtained.  

假设空集的GCD为1。 但是,如果n很大,那么将有2 ^ n个子集,这将不能最佳地工作。我该如何优化呢?

2 个答案:

答案 0 :(得分:1)

假设每个数组元素都是1..U范围内的整数,对于某些U.

设f(x)为GCD(x)的子集数。该问题的解决方案是所有不同因子1< = d< = U的总和d ^ f(d)。

设g(x)是可被x整除的数组元素的数量。

我们有

f(x) = 2^g(x) - SUM(x | y, f(y))

我们可以通过枚举每个数组元素的所有除数来计算O(n * sqrt(U))中的g(x)。通过以直接的方式枚举x的每个倍数,可以在O(U log U)中从高值到低值计算f(x)。

答案 1 :(得分:1)

先决条件

费马的小定理(也有一个广义定理),简单的数学,模幂运算

说明:符号:A []代表我们的输入数组

显然约束1< = N< = 10 ^ 5,告诉我你需要一个O(N * LOG N)解决方案,不要试图认为DP因为它的复杂性根据我将是N * max(A [i])即约。 10 ^ 5 * 10 ^ 6。为什么?因为你需要子集的GCD来进行转换。

好的,继续前进

我们可以考虑使用相同的GCD对子集进行分组,以便提高复杂性。

所以,让迭代器从10 ^ 6递减到1试图用GCD制作集合!

现在用GCD制作子集(i)我可以用任何i * j来组合它,其中j是非负整数。为什么?

GCD(i,i * j)= i

现在,

我们可以为任何元素构建一个频率表,因为数字是可以访问的!

现在,在比赛期间,我所做的是,将gcd(i)的子集数保持在f2 [i]

因此我们所做的是来自j * i的所有元素的总和频率,其中j从1变化到地面(i / j) 现在带有公约数(而不是GCD)的子集为i(2 ^ sum - 1)。

现在我们必须从这个总和中减去GCD大于i的子集,并将i作为gcd的公约数作为i。

这也可以在同一个循环中通过取f2 [i * j]求和,其中j从1变化到地面(i / j)

现在GCD的子集i等于2 ^ sum -1 - f2 [ij]的总和恰好乘以i(子集的数量与GCD的次数i次)即幂(i,2 ^ sum -1 - f2的总和[ij])。但现在计算这个指数部分可以溢出,但你可以用给定MOD-1的%,因为MOD是素数! (费马小定理)使用模幂运算

以下是我的代码片段,因为我不确定我们现在可以发布代码了吗?

for(i=max_ele; i >= 1;--i)
            {
                to_add=F[i];
                to_subtract = 0 ;
                for(j=2 ;j*i <= max_ele;++j)
                    {
                        to_add+=F[j*i];
                        to_subtract+=F2[j*i];
                        to_subtract>=(MOD-1)?(to_subtract%=(MOD-1)):0;
                    }

                subsets = (((power(2 , to_add , MOD-1) ) - 1) - to_subtract)%(MOD-1) ;

            if(subsets<0)
                subsets = (subsets%(MOD-1) +MOD-1)%(MOD-1);

            ans  = ans * power(i , subsets , MOD);
            F2[i]= subsets;
            ans %=MOD;
        }

我觉得我使用F2让事情变得复杂,我觉得我们可以在没有F2的情况下通过不采用j = 1来做到这一点。但是没关系我没想到它这是我是如何设法获得AC的。

相关问题