寻找因素

时间:2015-10-01 05:27:02

标签: c++ factors

我正在做一个C ++程序,因为我需要从数组中找到具有共同因子的数字。我已经以天真的方式做了。

int commonFactors(int p, int q){
    int count = 0;

    if(q > p){
        for(int i = 2;i < q;i++){
            if((q%i==0)&&(p%i==0)){
                count++;
                break;
            }
        }
    }
    else if(p > q){
        for(int i = 2;i < p;i++){
            if((p%i==0)&&(q%i==0)){
                count++;
                break;
            }
        }
    }
    else{
        count = 1;
    }

    return count;
}

然后我的代码超时以获得更大的输入。对于阵列中的任何元素,我的输入范围是1到1000000。有关如何有效计算它的任何线索?

我只想检查主要因素,但我担心要检查的范围。

5 个答案:

答案 0 :(得分:2)

如果唯一的问题是&#34;这两个问题是否有一个共同的因素(除了一个)&#34;,那么一个选项就是计算它们最大的公约数,并检查它是否为1。使用Euclidean algorithm可以相当有效地计算GCD(绝对比计算一直到你的数字更快):

gcd(a, 0) = a
gcd(a, b) = gcd(b, a % b)

答案 1 :(得分:0)

你可以通过运行for循环到&#34; sqrt(p)&#34;来更有效地完成它。 (或q,取决于较少的课程数)。 这应该可以加快速度。

答案 2 :(得分:0)

考虑两个数字:9240和16170.每个数字都可以写成(少数)素数的乘积:

9240 = 2*2*3*5*7*11
16170 = 2*3*5*7*7*11

从上面的示例中可以明显看出,可能的公共因子的总数将是您可以使用这些操作数创建的总数字列表。在这种情况下,一组数字23511将产生15个总组合。

所以你的代码可以执行以下步骤(我不会为你编写C ++代码,因为你应该可以自己轻松编写代码):

  
      
  1. 使用Integer factorization
  2. 将每个数字拆分为其素数因子   
  3. 查找每个列表中存在的那些素数的完整子集(不要忘记某些列表中的某些素数可能会出现多次,应该被视为单独的素数,即两次)
  4.   
  5. 通过组合给定的素数组
  6. 找到您可以创建的所有可能数字   

对于最后一部分,您可以看到Dynamic programming有关如何提高其效果显着naïve方法相比的想法。

答案 3 :(得分:0)

首先是一些数学:说A和B是两个正非空整数,让我们称C = gcd(A,B)是A和B的最大公约数,然后如果M除以A和B,M除C

所以如果你只想知道A和B是否有公约数,你只需要检查C是否大于1,如果你想知道所有公约数(或它们的数)你必须找到C的所有除数

找到两个数字的GCD的欧几里德算法基于以下属性:比如说B&lt; A,A = P * Q + R是P乘以Q的欧氏分裂,那么如果R = 0,则GCD(A,B)= B,否则GCD(A,B)= GCD(B,R)(ref { {3}})

现在有些代码:

/* Euclidian algorythm to find Greatest Common Divisor
 Constraint (not controled here) p>0 and q>0 */
int gcd(int p, int q) {
    // ensures q < p
    if (p < q) {
        int temp = p;
        p = q;
        q = temp;
    }
    int r = p % q;
    // if q divises q, gcd is q, else gcd(p, q) is gcq(q, r)
    return (r == 0) ? q : gcd(q, r);
}

bool sharedivisors(int p, int q) {
    int d = gcd(p, q);
    return d > 1;
}

int divisors(int p, int q) {
    int d = gcd(p, q);
    if (d == 1) {
        return 1;
    }
    int count = 0;
    for(int i=2; i<d/2; i++) {
        if(d % i == 0) {
            int j = d/i;
            if (j > i) count += 2;
            else {
                if (j == i) count += 1;
                break;
            }
        }
    }
    return count + 2; // and 1 and d
}

答案 4 :(得分:0)

从2到更大输入的计数因子是强力并且持续很长时间,即使其中一个输入很大。 普通除数的数量可以从他们的素数因子分解的指数中获得。更容易计算他们最大的公约数

gcd = gcd( p0, q0 )
/* .. */
int gcd( p0, q0 )
{
    while( q0 )
    {
        int swp = q0;
        q0 = p0 % q0;
        p0 = swp;
    }
    return p0;
}

然后计算其除数

  • 以naiv方式(如有问题)
  • 总是将gcd与找到的除数分开
  • 通过素数分解

    p0^x0 * p1^x1 * .. * pN^xN = gcd
    count = (1+x0) * (1+x1) * .. * (1+xN)
    

素数因子化要求素数列表最多为sqrt(gcd)。