没有大于 k 的素因数的正数
Positive number which has no prime factor greater than k
我试图创建一个函数,它接受两个变量n
和k
。
该函数返回素因数全部小于或等于 k
的正整数的数目。正整数的数量受最大正整数n
的限制。
例如,如果 k = 4
和 n = 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)
- 大于65535的C++数组[size]引发不一致的溢出
- 查找最接近的大于当前数字的数字的索引
- 如何找到大于整数的最小数字
- 为什么签名字符可以保存大于 127 的值?
- 如何打印大于"无符号长长"的"std::bitset"的十进制值?
- 为什么它总是给我大于 4?
- 如果变量数据包含大于 vector 所有元素的整数,则仅在视觉工作室上接收"矢量下标超出范围"?
- 在向量中查找大于 0(或通常为 k)的最小元素的最佳方法是什么?
- 使用 RapidXML 解析大型 XML(大小大于 65 KB)文件时出现问题
- CStdioFile 不能处理大于 2GB 的文件?
- 当我选择大于 720 的矩阵大小时,程序退出并显示错误代码.可能是什么原因?
- C++大于或等于运算符
- 除数大于两个大因子时的模积
- 如何查找数字大于 5 的数字总和
- 数组大于指定大小(C++)
- 16 位系统中的程序如何访问大于 65535 的整数,但不能访问地址
- 第 k 个最小元素 - 不能创建大于 k 大小的数组
- 特征::向量;在函数中使用 Eigen::Matrix3f 的值初始化向量,大于 4 个条目
- 如何在随机数列表中查找大于或小于的元素
- 在MSDOS编译器上,用大于最大值的值初始化int时输出混乱