发现的因素
Finding 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。知道如何有效地计算它吗?
我有一个只检查质因数的想法,但我担心检查的范围
如果唯一的问题是"这两个是否有公约数(除了一个)",那么一个选项就是计算它们的最大公约数,并检查它是否为1。使用欧几里得算法可以相当有效地计算GCD(绝对比一直数到你的数字快):
gcd(a, 0) = a
gcd(a, b) = gcd(b, a % b)
你可以更有效地运行for循环直到"sqrt(p)"(或者是q,当然取决于更小的数)这应该已经加快了速度。
考虑两个数字:9240和16170。每个数都可以写成几个质数的乘积:
9240 = 2*2*3*5*7*11
16170 = 2*3*5*7*7*11
从上面的示例中可以明显看出,可能的公共因子的总数将是您可以用这些操作数创建的数字的总列表。在这种情况下,2
, 3
, 5
和11
的数字集合将产生15
个总组合。
所以你的代码可以执行以下步骤(我不打算为你编写c++代码,因为你应该能够轻松地自己完成):
- 使用整数分解将每个数字分解为其质因数
- 查找每个列表中存在的素数的完整子集(不要忘记有些素数可能在两个列表中出现不止一次,应该作为单独的素数计算,即两次)
- 找到所有可能的数字,你可以通过组合一组给定的素数
对于本文的最后一部分,您可以查看动态规划,了解如何显著提高其性能与naïve方法相比。
首先是一些数学问题:假设A和B是两个正非空整数,设C= gcd(A, B)是A和B的最大公约数,则如果M能整除A和B,则M能整除C。
所以如果你只想知道A和B是否有公因数你只需要检查C是否大于1,如果你想知道所有的公因数(或它们的个数)你必须找到C的所有因数
求两个数的GCD的欧几里得算法基于以下性质:A, A = P * Q + R是P除以Q的欧几里得除法,则如果R = 0, GCD(A,B) = B,否则GCD(A,B) = GCD(B,R) (ref wikipedia)
现在一些代码:
/* 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
}
从2到更大的输入是蛮力,即使其中一个输入很大,也会持续很长时间。公因数的个数可以由它们的质因数分解的指数得到。更容易先计算它们的最大公约数
gcd = gcd( p0, q0 )
/* .. */
int gcd( p0, q0 )
{
while( q0 )
{
int swp = q0;
q0 = p0 % q0;
p0 = swp;
}
return p0;
}
,然后计算其除数
- 以天真的方式(如问题)
- 总是用找到的除数除gcd
质因数分解
p0^x0 * p1^x1 * .. * pN^xN = gcd count = (1+x0) * (1+x1) * .. * (1+xN)
质因数分解需要质数列表直到sqrt(gcd)
- CTest 项目目录.未发现任何测试
- 请发现它在 dev 中工作的错误,但在 hackerrank 中不起作用
- 我的 c++ 程序似乎没有发现字符串和我拥有但输入使用 getline 的变量之间的比较
- Nanoflann发现邻居提出段错误
- 我在玩VS2017时发现了一些东西
- 在使用另一个类"friend"函数时无法发现错误C++
- 在一次锻炼测试中发现致命信号11
- Visual Studio 2017 单元测试与 C++ 和 C# 与未发现的C++测试
- 为什么没有发现我的异常
- 我在微控制器STM32F373发现中点亮LED的问题
- 无法发现嵌套的循环错误
- 应由于计算费用而避免对STD的多个调用::发现,否则这是可以接受的情况
- 我在C 初学者中发现了无限的循环问题
- 字符串C :libc abi.dylib:终止未被发现的类型std :: out_of_range:basic
- 奇怪的行为发现了 c++ sdl2
- 在一个文件中定义多个类时,我发现我的主函数无法访问较低类中的函数
- 联合发现形状是在一侧还是另一侧
- 当我使用py 生成时,然后在macOS上boost.python包装器时,我会发现有关std :: string的错
- 如何在使用和无发现的情况下使用和不使用的字符串向量搜索元素
- 发现Cmake是通过SDK工具安装的