两个数字的公共因子总数大到10 ^ 12

时间:2017-04-18 22:57:38

标签: c++ performance

输入是两个值1 <= m,n <= 10 ^ 12 我不知道为什么我的代码需要很长时间才能获得大值。时间限制是1秒。请给我一些重要的修改。

#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
unsigned long long m,n,count=0;
cin >> m >> n;  
for (long long int i = 1; i <= ((min(m,n))/2)+1; i++) //i divided min(m,n) by 2 to make it efficient.
{

    if ((m%i == 0) && (n%i == 0))
    {
        count++;
    }

}
if (((n%m == 0) || (m%n == 0)) && (n!=m))
{
    cout << count << endl;
}

printf("%lld",count);  //cout<<count;

system("pause");
return 0;

}

2 个答案:

答案 0 :(得分:1)

首先

((min(m, n)) / 2) + 1

每次迭代都要计算。但它的循环不变。通常,循环不变代码可以在循环之前计算并存储。它会加起来,但显然有更好的方法来改进。我将在下面描述一个:

你可以通过计算有多少常见的素因子,并通过除去任何&#34;找到&#34;来更快地做到这一点。当你去的时候。例如如果只有一个数字可以被5整除,而另一个数字不能被整除,你可以将那个数除以5,你仍然可以得到相同的公共因子答案。将m和n除以任何&#34;找到&#34;你经历过的数字。 (但要继续检查是否可以被2整除,并在继续之前继续分割。)

e.g。如果两个数字都可以被2,3和5整除,那么这三个素数可以组合的方式的数量是8(2 ^ 3),将每个素数的存在视为真/假。因此,每次出现的素数都会使组合数乘以2。

如果任何素数出现不止一次,那么它会略微改变等式。例如如果这两个数字可以被4,3,5整除:

4 = 2 ^ 2,所以你可能没有&#34; 2s&#34;,1&#34; 2&#34;或2&#34; 2s&#34;在组合因子中,总组合3 x 2 x 2 = 12.因此任何发生的素数&#34; x&#34;时间,将组合的总数乘以&#34; x + 1&#34;。

所以基本上,你不需要检查每个实际因素,你只需要搜索有多少常见素因子,然后计算出多少组合。幸运的是,你只需要存储一个值,&#34; total_combos&#34;并乘以&#34; x + 1&#34;你去的每个找到的数字的值。

一个方便的事情是,你可以在找到所有素数时将它们分开,并且你可以保证找到的最大剩余素数不大于最小剩余数的平方根。在m和n之外。

因此,为了让您了解这将如何工作,从m和n的副本开始,循环到这两个的min的sqrt(m和n将随着循环循环而减少)。

制作一个值&#34; total_combos&#34;,从1开始。

首先检查2,找出2的常用功率,加1到该数字。将m和n中的所有2分开,即使它们不匹配,因为减少数字会减少您实际需要搜索的总金额。你计算2&#39; s,加1,然后乘以&#34; total_combos&#34;那个。只要剩下两个因子,就保持将m或n除以2。

然后检查3,找出3的常用功率,加1,乘以&#34; total_combos&#34;那个。当你这样做时,将3的所有因素分开。

然后检查4&#39。由于4不是素数,我们已经摆脱了所有的2,所以将会有4个零。添加一个到= 1,然后我们计时&#34; total_combos&#34; 1,所以它保持不变。我们不需要检查4是否是素数,我们已经做过的分歧确保它被忽略了。任何2的力量都相同。

然后检查5&#39>。与2&3和3相同的交易。等等。所有的基本基础都会随着时间的推移而分开,所以每当一个值实际匹配时,你就可以确定它是一个新的素数。

当它超过sqrt(max(m,n))时停止循环(EDITED:min可能是错误的)。但是这里的m和n是将所有较低素数分开的值,因此速度要快得多。

我希望这种方法很有用。

答案 1 :(得分:1)

有一个更好的方法可以解决此问题。 您所要做的就是获取两个数字的 GCD 。现在,任何大于m G的数字都不会除m&n。因此,您要做的就是循环运行,直到 i <= Math.sqrt(GCD(m,n))并检查m%i == 0和n%i == 0只要。它将节省很多纳秒。