Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 快速求两组数的公素数_C++_Math_Optimization_Primes - Fatal编程技术网

C++ 快速求两组数的公素数

C++ 快速求两组数的公素数,c++,math,optimization,primes,C++,Math,Optimization,Primes,我一直在努力解决这个问题: 我有它在返回正确答案方面的功能,但对于较大的数字来说,它的速度非常慢,我想看看是否有人能更好地更快地完成它,或者解释我可以优化它的方法 bool IsPrime(int number) { for (int i = 2; i < number; i++) { if (number % i == 0) { return false; } } return tr

我一直在努力解决这个问题:

我有它在返回正确答案方面的功能,但对于较大的数字来说,它的速度非常慢,我想看看是否有人能更好地更快地完成它,或者解释我可以优化它的方法

bool IsPrime(int number)
{
    for (int i = 2; i < number; i++)
    {
        if (number % i == 0)
        {
            return false;
        }
    }

    return true;    
}

bool GetPrimeFactors(int valueA, int valueB)
{
    if(valueA < 0 || valueB < 0)
        return false;

    int max = sqrt(std::max(valueA, valueB)) + 1;//sqrt(std::max(valueA, valueB));
    std::vector<int> factors;
    bool oneSuccess = false;
    for(int i = 2; i <= max; i++)
    {
        bool remainderA = valueA % i == 0;
        bool remainderB = valueB % i == 0;
        if(remainderA != remainderB)
            return false;
        if(IsPrime(i))
        {
            //bool remainderA = valueA % i == 0;
           // bool remainderB = valueB % i == 0;

            if(remainderA != remainderB )
            {
                return false;
            }
            else if(!oneSuccess && remainderA && remainderB)
            {
                oneSuccess = true;
            }
        }
    }

    return true;
}

int solution(vector<int> &A, vector<int> &B) {
    int count = 0;
    for(size_t i = 0; i < A.size(); i++)
    {
        int valA = A[i];
        int valB = B[i];

        if(GetPrimeFactors(valA, valB))
            ++count;
    }

    return count;
}
bool IsPrime(整数)
{
for(int i=2;i更新的):

bool IsPrime(整数)
{
如果(数字%2==0)
{
返回(数字=2);
}
整数极限=sqrt(数字);

对于(inti=3;i你实际上不需要找到数字的素数因子来决定它们是否有相同的素数因子

这是我想出的一个通用算法,用于检查
a
b
是否具有相同的素因子。这将比素因子分解
a
b
快得多

  • 如果
    a==b
    ,答案是
    true
  • 如果
    a==1 | | b==1
    ,则答案为
    false
  • 用于查找2个数字的GCD。如果
    GCD==1
    ,则答案为
    false
  • 请注意,
    GCD
    需要包含两个数字的所有素数因子才能得到正确答案,因此请检查
    newa=a/GCD
    newb=b/GCD
    是否可以通过重复将它们除以
    Euclid(newa,GCD)
    Euclid(newb,GCD)而减少为1
    直到
    newa
    newb
    到达
    1
    哪个成功,或者
    Euclid(newa,GCD)
    或者
    Euclid(newb,GCD)
    返回
    1
    哪个失败
  • 让我们看看这对a=75,b=15是如何起作用的: 1) GCD=欧几里德(75,15)=15 2) newa=75/15=5,newb=15/15=1,用newb完成 3) 纽瓦=5/欧几里德(5,15)=5/5=1成功! a=6,b=4怎么样: 1) GCD=欧几里德(6,4)=2 2) 新A=6/2=3,新B=4/2=2 3) 欧几里德(纽瓦,2)=欧几里德(3,2)=1失败! a=2,b=16怎么样: 1) GCD=欧几里德(2,16)=2 2) newa=2/2=1(这很好),newb=16/2=8 3) 纽布=8/欧几里德(8,2)=8/2=4 4) 纽布=4/欧几里德(4,2)=4/2=2 5) newb=2/欧几里德(2,2)=2/2=1成功!
    发现了非常详细的解释:

    假设两个数
    N
    M
    ,用素数分解,然后将
    N
    M
    的GCD表示为
    P1*P2*P3*P4*…Px
    (每一个都是
    GCD(N,M)
    )的素因子。然后,表示
    N/GCD(N,M)
    M/GCD(N,M)
    分别用它们的素因子表示为
    N1*N2*N3*…Ny
    M1*M2*M3*…Mz
    ;然后,
    N
    M
    可以表示如下

    N = (P1 * P2 * P3 ... Px) * N1 * N2 * N3 * ... Ny
    M = (P1 * P2 * P3 ... Px) * M1 * M2 * M3 * ... Mz
    
    由于
    (P1*P2*P3…Px)
    gcd(N,M)
    ,因此
    N
    M
    共有的任何素数因子总是在
    (P1,P2,P3,…Px)
    中至少出现一次

    换句话说,如果在
    (P1,P2,P3,…Px)
    中找不到“
    N/gcd(N,M)
    (N1,N2,N3…Ny)
    的任何素数因子,它就不是
    M
    的素数因子。因此,可以说
    N
    M
    的素数因子集并不完全相同

    类似地,如果在
    (P1,P2.P3,…Px)
    中找不到“
    M/gcd(A,B)
    (M1,M2,L3…Ly)
    的任何素数因子,它就不是
    N
    的素数因子,可以说
    N
    M
    的素数因子集并不完全相同

    因此,问题只是检查
    N1 Ny
    M1 Mz
    中的任何一个是否从未出现在
    P1 Px

    现在让我们考虑一下。让<代码> x= n/gCD(n,m)< /代码>,考虑<代码> gCD(gCD(n,m),x)< /c> > /p> 目前,情况如下

    gcd(N,M): P1 * P2 * P3 ... Px
    X       : N1 * N2 * N3 ... Ny
    
    如果
    gcd(N,M)%X==0
    ,那么
    X
    的所有素因子都包含在
    gcd(N,M)

    如果不是,那么我们计算
    gcd(gcd(N,M,X)
    。如果这两个值的gcd只有1,这意味着
    N1 Ny
    中没有一个出现在
    p1px
    中;这意味着
    N
    值有一个不与
    M
    共享的素数因子

    如果gcd大于1,那么我们计算
    X/gcd(gcd(N,M),X)
    ,并在下一轮更新
    X
    。这意味着我们取出了
    X
    的一些素数因子,构成
    gcd(gcd(N,M),X)
    ,并将其用于下一轮


    如果此时
    gcd(N,M)%X==0
    ,这意味着
    X
    的所有素数因子都包含在
    gcd(N,M)
    中。如果没有,我们将重复上述操作。

    上述@vacawama解决方案的python实现

    def gcd_division(a, b):
        if not a%b:
            return b
        return gcd_division(b, a%b)
    
    def prime_reduce(n, gcd):
        na = n // gcd
        ngcd = gcd_division(na, gcd)
        if na == 1:
            return True # success base case
        elif ngcd == 1:
            return False
        return prime_reduce(na, ngcd)
    
    def solution(A, B):
        Z = len(A)
        result = 0
        for i in range(0, Z):
            a, b = A[i], B[i]
            if a == b:
                result += 1
            else:
                gcd = gcd_division(a, b)
                result += (prime_reduce(a, gcd) and prime_reduce(b, gcd))
        return result
    
    我使用以下测试用例运行它

    if __name__ == '__main__':
        test_cases = (
            (1, ([15, 10, 9], [75, 30, 5]) ),
            (2, ([7, 17, 5, 3], [7, 11, 5, 2]) ),
            (2, ([3, 9, 20, 11], [9, 81, 5, 13]) ),
        )
        for expected, args in test_cases:
            got = solution(*args)
            print('result', expected, got)
            assert(expected == got)
    

    它的100%

    Java实现基于的答案:

      class Solution {
        public int solution(int[] A, int[] B) {
            int count = 0;
            for(int i = 0; i < A.length; i++){
                if(A[i] == B[i]) count++;
                else if(A[i] == 1 || B[i] == 1) continue;
                else{
                    int GCD = gcd(A[i], B[i]);
                    
                    if(GCD == 1) continue;
                    
                    int newA = A[i]/GCD;
                    int newB = B[i]/GCD;
                    
                    if(checkDiv(newA, GCD) && checkDiv(newB, GCD)) count++;
                } 
            }
            
            return count;
        }
        
        public boolean checkDiv(int num, int gcd){
            
            if(num == 1) return true;
            else if(gcd == 1) return false;
            
            else {
                gcd = gcd(gcd, num);
                num = num/gcd;
            
                return checkDiv(num, gcd);
            }
        }
        public int gcd(int a, int b){
            if(b == 0) return a;
            else return gcd(b, a % b);
        }
    }
    
    类解决方案{
    公共int解决方案(int[]A,int[]B){
    整数计数=0;
    for(int i=0;iif __name__ == '__main__':
        test_cases = (
            (1, ([15, 10, 9], [75, 30, 5]) ),
            (2, ([7, 17, 5, 3], [7, 11, 5, 2]) ),
            (2, ([3, 9, 20, 11], [9, 81, 5, 13]) ),
        )
        for expected, args in test_cases:
            got = solution(*args)
            print('result', expected, got)
            assert(expected == got)
    
      class Solution {
        public int solution(int[] A, int[] B) {
            int count = 0;
            for(int i = 0; i < A.length; i++){
                if(A[i] == B[i]) count++;
                else if(A[i] == 1 || B[i] == 1) continue;
                else{
                    int GCD = gcd(A[i], B[i]);
                    
                    if(GCD == 1) continue;
                    
                    int newA = A[i]/GCD;
                    int newB = B[i]/GCD;
                    
                    if(checkDiv(newA, GCD) && checkDiv(newB, GCD)) count++;
                } 
            }
            
            return count;
        }
        
        public boolean checkDiv(int num, int gcd){
            
            if(num == 1) return true;
            else if(gcd == 1) return false;
            
            else {
                gcd = gcd(gcd, num);
                num = num/gcd;
            
                return checkDiv(num, gcd);
            }
        }
        public int gcd(int a, int b){
            if(b == 0) return a;
            else return gcd(b, a % b);
        }
    }
    
    
    function solution(A, B) {
    
        function getGcd(a,b, res = 1) {
            if (a === b) return res * a;
            if (a % 2 === 0 && b % 2 === 0) return getGcd(a/2, b/2, 2 * res);
            if (a % 2 === 0) return getGcd(a/2, b, res);
            if (b % 2 === 0) return getGcd(a, b/2, res);
            if (a > b) return getGcd(a-b, b, res);
            else return getGcd(a, b-a, res);
        }
    
        const hasCommonPrimeDivisors = (a, b) => {
            if (a === b) return true;
            if (a === 1 || b === 1) return false;
            let gcd = getGcd(a, b);
            if (gcd === 1) return false;
            while (a !== 1 || b !== 1) {
                let newGcd;
                if (a !== 1) {
                    newGcd = getGcd(a, gcd);
                    if (newGcd === 1) {
                        return false;
                    }
                    a = a / newGcd;
                }
    
                if (b !== 1) {
                    newGcd = getGcd(b, gcd);
                    if (newGcd === 1) {
                        return false;
                    }
                    b = b/newGcd;
                }
            }
            return true;
        }
    
        let count = 0
        A.forEach((a, index) => {
            const b = B[index];
            if (hasCommonPrimeDivisors(a, b)) {
                count++;
            }
        })
        return count;
    }