没有大于 k 的素因数的正数

Positive number which has no prime factor greater than k

本文关键字:大于      更新时间:2023-10-16

我试图创建一个函数,它接受两个变量nk

该函数返回素因数全部小于或等于 k 的正整数的数目。正整数的数量受最大正整数n的限制。

例如,如果 k = 4n = 10 ;所有素因数都小于或等于 4 的正整数是 1, 2, 3, 4, 6, 8, 9, 12...(由于某种原因,1 总是一部分,即使它不是素数(,但由于 n 是 10,因此忽略 12 和更大的数字。

因此,该函数将返回 7。我编写的代码适用于较小的n值,而它只是继续运行较大的值。

如何优化此代码?我应该从头开始并提出更好的算法吗?

int generalisedHammingNumbers(int n, int k)
{
    vector<int>store;
    vector<int>each_prime = {};
    for (int i = 1; i <= n; ++i)
    {
        for (int j = 1; j <= i; ++j)
        {
            if (i%j == 0 && is_prime(j))
            {
                each_prime.push_back(j);   //temporary vector of prime factors for each integer(i) 
            }
        }
        for (int m = 0; m<each_prime.size(); ++m)
        {
            while(each_prime[m] <= k && m<each_prime.size()-1)  //search for prime factor greater than k
            {
                ++m;
            }
            if (each_prime[m] > k);  //do nothing for prime factor greater than k
            else store.push_back(i);  //if no prime factor greater than k, i is valid, store i
        }
        each_prime = {};
    }
    return (store.size()+1);
}
bool is_prime(int x)
{
    vector<int>test;
    if (x != 1)
    {
        for (int i = 2; i < x; ++i)
        {
            if (x%i == 0)test.push_back(i);
        }
        if (test.size() == 0)return true;
        else return false;
    }
    return false;
}

int main() 
{
    long n;
    int k;
    cin >> n >> k;
    long result = generalisedHammingNumbers(n, k);
    cout << result << endl;

}

我应该从头开始并提出更好的算法吗?

是的。。。我认为如此。

在我看来,这是埃拉托色尼筛子的作品。

所以我建议

1(创建一个std::vector<bool>,通过埃拉托色尼检测

素数n

2( 从数字池中删除从 k+1 开始的素数及其倍数(另一个std::vector<bool>(

3( 计算池向量中的剩余true

以下是完整的工作示例

#include <vector>
#include <iostream>
#include <algorithm>
std::size_t foo (std::size_t n, std::size_t k)
 {
   std::vector<bool> primes(n+1U, true);
   std::vector<bool> pool(n+1U, true);
   std::size_t const sqrtOfN = std::sqrt(n);
   // first remove the not primes from primes list (Sieve of Eratosthenes)
   for ( auto i = 2U ; i <= sqrtOfN ; ++i )
      if ( primes[i] )
         for ( auto j = i << 1 ; j <= n ; j += i )
            primes[j] = false;
   // then remove from pool primes, bigger than k, and multiples
   for ( auto i = k+1U ; i <= n ; ++i )
      if ( primes[i] )
         for ( auto j = i ; j <= n ; j += i )
            pool[j] = false;
   // last count the true value in pool (excluding the zero)
   return std::count(pool.begin()+1U, pool.end(), true);
 }
int main ()
 {
   std::cout << foo(10U, 4U) << std::endl;
 }
使用埃

拉斯托色尼筛生成素数,然后使用修改后的硬币兑换算法来查找仅是这些素数乘积的数字。事实上,可以像这样同时执行这两个操作(在 Python 中,但很容易转换为 C++(:

def limited_prime_factors(n, k):
    ps = [False] * (k+1)
    r = [True] * 2 + [False] * n
    for p in xrange(2, k+1):
        if ps[p]: continue
        for i in xrange(p, k+1, p):
            ps[i] = True
        for i in xrange(p, n+1, p):
            r[i] = r[i//p]
    return [i for i, b in enumerate(r) if b]
print limited_prime_factors(100, 3)

输出为:

[0, 1, 2, 3, 4, 6, 8, 9, 12, 16, 18, 24, 27, 32, 36, 48, 54, 64, 72, 81, 96]

在这里,每次我们找到一个素数p,我们删除ps数组中所有p的倍数(作为标准的埃拉斯托梯尼筛(,然后在r数组中,标记任何数字的所有倍数,p的倍数,无论它们的素因数是否都小于或等于p

它在 O(n( 空间和 O(n log log k( 时间内运行,假设 n>k。

更简单的 O(n log k( 解测试一个数字的所有因子是否小于或等于 k:

def limited_prime_factors(n, k):
    r = [True] * 2 + [False] * n
    for p in xrange(2, k+1):
        for i in xrange(p, n+1, p):
            r[i] = r[i//p]
    return [i for i, b in enumerate(r) if b]

这是Python中的欧拉版本(似乎比Paul Hankin快1.5倍(。我们通过将列表依次乘以每个素数及其幂来仅生成数字本身。

import time
start = time.time()
n = 1000000
k = 100
total = 1
a = [None for i in range(0, n+1)]
s = []
p = 1
while (p < k):
  p = p + 1
  if a[p] is None:
    #print("nnPrime: " + str(p))
    a[p] = True
    total = total + 1
    s.append(p)
    limit = n / p
    new_s = []
    for i in s:
      j = i
      while j <= limit:
        new_s.append(j)
        #print j*p
        a[j * p] = True
        total = total + 1
        j = j * p
    s = new_s
print("nnGilad's answer: " + str(total))
end = time.time()
print(end - start)
# Paul Hankin's solution
def limited_prime_factors(n, k):
    ps = [False] * (k+1)
    r = [True] * 2 + [False] * n
    for p in xrange(2, k+1):
        if ps[p]: continue
        for i in xrange(p, k+1, p):
            ps[i] = True
        for i in xrange(p, n+1, p):
            r[i] = r[i//p]
    return len([i for i, b in enumerate(r) if b]) - 1
start = time.time()
print "nPaul's answer:" + str(limited_prime_factors(1000000, 100))
end = time.time()
print(end - start)