有什么简单而高效的逻辑可以找出给定数字的因数吗?是否存在基于此的算法。
事实上,我真正的问题是找出给定数字存在的因数数量。
请告诉我任何算法,谢谢。
谢谢。
有什么简单而高效的逻辑可以找出给定数字的因数吗?是否存在基于此的算法。
事实上,我真正的问题是找出给定数字存在的因数数量。
请告诉我任何算法,谢谢。
谢谢。
read given number in n
initial_n = n
num_factors = 1;
for (i = 2; i * i <= initial_n; ++i) // for each number i up until the square root of the given number
{
power = 0; // suppose the power i appears at is 0
while (n % i == 0) // while we can divide n by i
{
n = n / i // divide it, thus ensuring we'll only check prime factors
++power // increase the power i appears at
}
num_factors = num_factors * (power + 1) // apply the formula
}
if (n > 1) // will happen for example for 14 = 2 * 7
{
num_factors = num_factors * 2 // n is prime, and its power can only be 1, so multiply the number of factors by 2
}
18
。 18 = 2^1 * 3*2 => 因子数量 = (1 + 1)*(2 + 1) = 6
。确实,18
的6
个因子是1, 2, 3, 6, 9, 18
。 class Program
{
static private List<int> primes = new List<int>();
private static void Sieve()
{
bool[] ok = new bool[2000];
for (int i = 2; i < 2000; ++i) // primes up to 2000 (only need up to sqrt of 1 000 000 actually)
{
if (!ok[i])
{
primes.Add(i);
for (int j = i; j < 2000; j += i)
ok[j] = true;
}
}
}
private static int IVlad(int n)
{
int initial_n = n;
int factors = 1;
for (int i = 0; primes[i] * primes[i] <= n; ++i)
{
int power = 0;
while (initial_n % primes[i] == 0)
{
initial_n /= primes[i];
++power;
}
factors *= power + 1;
}
if (initial_n > 1)
{
factors *= 2;
}
return factors;
}
private static int Maciej(int n)
{
int factors = 1;
int i = 2;
for (; i * i < n; ++i)
{
if (n % i == 0)
{
++factors;
}
}
factors *= 2;
if (i * i == n)
{
++factors;
}
return factors;
}
static void Main()
{
Sieve();
Console.WriteLine("Testing equivalence...");
for (int i = 2; i < 1000000; ++i)
{
if (Maciej(i) != IVlad(i))
{
Console.WriteLine("Failed!");
Environment.Exit(1);
}
}
Console.WriteLine("Equivalence confirmed!");
Console.WriteLine("Timing IVlad...");
Stopwatch t = new Stopwatch();
t.Start();
for (int i = 2; i < 1000000; ++i)
{
IVlad(i);
}
Console.WriteLine("Total milliseconds: {0}", t.ElapsedMilliseconds);
Console.WriteLine("Timing Maciej...");
t.Reset();
t.Start();
for (int i = 2; i < 1000000; ++i)
{
Maciej(i);
}
Console.WriteLine("Total milliseconds: {0}", t.ElapsedMilliseconds);
}
}
我的机器上的结果:
测试等价性...
确认等价性!
计时IVlad...
总毫秒数:2448
计时Maciej...
总毫秒数:3951
按任意键继续. . .
i
是n
的因子,那么n / i
也是它的因子。这是另一种方法,也允许只进行到平方根,只需确保i
和n / i
不同,以便不重复计算!但是,这不能让你只检查质数,所以我认为它不总是更快(使用我的发布方法,您可以预先计算质数以使其更快)。例如,对于20
,您必须检查4
才能意识到在您描述的方法中4
和5
是因子(如果我想到的是同一件事情)。 - IVlad有大量的算法可用 - 从简单的试除法到针对大数的非常复杂的算法。请查看维基百科上的整数分解,选择适合您需求的算法。
这里是一个简短但效率低下的C#实现,可以找到质因子的数量。如果您需要因子的数量(而不是质因子),则必须存储带有其重复性的质因子,并在此之后计算因子的数量。
var number = 3 * 3 * 5 * 7 * 11 * 11;
var numberFactors = 0;
var currentFactor = 2;
while (number > 1)
{
if (number % currentFactor == 0)
{
number /= currentFactor;
numberFactors++;
}
else
{
currentFactor++;
}
}
numberFactors
将包含值 3
(对于 18
),这是错误的,18
中只有2
个质因数:2
和3
。 - IVladread given number in n
int divisorsCount = 1;
int i;
for(i = 2; i * i < n; ++i)
{
if(n % i == 0)
{
++divisorsCount;
}
}
divisorsCount *= 2;
if(i * i == n)
{
++divisorsCount;
}
n
的平方根。我的方法有可能只迭代质数。这种方法更容易实现,但只有在你不必多次运行它时才更可取。 - IVlad注意,这个答案对于单个n值不是有用/快速的。
方法1:
如果你维护一个查找表(用于一个数字的第一个质因数),那么你可以在O(polylog(n))内得到它。
如果gcd(a,b) == 1,则a*b的因子数= a的因子数 * b的因子数。
因此,对于给定的数字a*b,如果gcd(a,b) != 1,则我们可以有另外两个数字p和q,其中p = a,q = b/gcd(a,b)。因此,gcd(p,q) == 1。现在,我们可以递归地找到p和q的因子数量。
只需要花费一些小的努力来确保p和q都不是1。
P.S. 当你需要知道从1到n的所有数字的因子数量时,这种方法也很有用。它将是O(nlogn + O(查找表))的顺序。
方法2:(我不拥有此方法。)
如果你有从1到n的第一个质因数的查找表,那么你可以在O(logn)时间内知道所有的质因数,并从中找出因子的数量。欧几里得算法应该足够了。