我正在尝试编写一个返回给定数字的素数因子化的函数(作为解决项目euler问题#12的一部分)。计算素因子。我使用std::map
。
代码如下:
#include "stdafx.h"
#include <iostream>
#include <map>
#include <algorithm>
bool IsPrime(unsigned int number)
{
if (number < 1) return 0; // zero is not prime. For our purposes, one would be.
for (unsigned int i = 2; i*i <= number; ++i)
{
if (number % i == 0)
return false;
}
return true;
}
int divisors(unsigned int num)
{
int orig_num = num;
std::map <int, int> primefactors;
for(unsigned int i = 1; i <= num; ++i)
if (num % i == 0 && IsPrime(i))
{
num /= i;
++primefactors[i];
std::cout << primefactors[i] << "\t";
}
std::cout << orig_num << " = ";
for(auto& iter:primefactors)
std::cout << iter.first << "^" << iter.second << " * ";
return 0;
}
int main()
{
divisors(661500);
return 0;
}
问题在于primefactors
的所有计数都返回为1,尽管main
中的数字被特别选择为素数乘以大于1的幂(661500 = 1 ^ 1 * 2 ^ 2 * 3 ^ 3 * 5 ^ 3 * 7 ^ 2)。
我的猜测是我正在增加错误。
答案 0 :(得分:4)
每个素数只划分一次。但只要数字可被整除,你就应该继续除以素数:
for(unsigned int i = 2; i <= num; ++i)
if (IsPrime(i))
{
while (num % i == 0) {
num /= i;
++primefactors[i];
std::cout << primefactors[i] << "\t";
}
}
实际上不需要IsPrime(i)
条件:
for(unsigned int i = 2; i <= num; ++i)
while (num % i == 0) {
num /= i;
++primefactors[i];
std::cout << primefactors[i] << "\t";
}
证明:如果i
不是素数,则条件num % i == 0
意味着num
可以被p
的素因子i
整除。但是p < i
所以我们的循环必须在p
之前的某个时间经过i
。并且while
循环将有效地删除p
中num
的所有出现。特别是在for
到达i
时,我们num
不再能被p
整除。矛盾。即如果满足num % i == 0
,则在上面的循环中,i
为素数。