有效地找到一个级数中的第n个数,其中这些数只能被2,3和5整除
Efficiently find the nth number in a series where the numbers are only divisible by 2,3 and 5
我想在一系列只能被2、3和5整除而不能被任何其他素数整除的数字中找到第n个数字。
这是我找到第1500个数字的最简单的解决方案。这大约需要16秒才能执行。我想知道是否有一种方法可以让它更快,比如使用多线程。
#include <iostream>
using namespace std;
int main()
{
int temp, seriesCounter = 1, currentNumber = 2;
while (seriesCounter < 1500)
{
temp = currentNumber;
//Remove all multiple of 2
while (temp % 2 == 0)
{
temp /= 2;
}
//Remove all multiple of 3
while (temp % 3 == 0)
{
temp /= 3;
}
//Remove all multiple of 5
while (temp % 5 == 0)
{
temp /= 5;
}
// If only 1 remains, the number is valid, else not.
if (temp == 1)
{
seriesCounter++;
}
currentNumber++;
}
cout << "The 1500th number in the series is : " << --currentNumber << endl << endl;
return 1;
}
这里有一个非常简单的方法。它在不到一秒钟的时间里找到了第1500个元素(我没想更精确地测量(。
#include <set>
#include <iostream>
int main() {
int n = 1500;
std::set<long long> s;
s.insert(2);
s.insert(3);
s.insert(5);
long long num = 0;
while (n--) {
num = *s.begin();
s.erase(s.begin());
s.insert(num*2);
s.insert(num*3);
s.insert(num*5);
}
std::cout << num;
}
在i7笔记本电脑上用0.000031秒完成的快速解决方案(结果:num[149]=860934420(:
时间复杂度为O(n((在您的情况下,n=1500(。假设当前序列为num[]。我们想把它增加到1500个元素。主要思想是记录序列num[]中的三个位置,我们称它们为idx[0]、idx[1]和idx[3]。使得2num[idx[0]、3num[idx[1]和5*num[idx[2]变得刚好>=序列中的最后一个数字(num.back(((。然后将三个数字中最小的一个加到序列的末尾(这将成为新的num.back(。
#include <iostream>
#include <vector>
#include <algorithm>
#include <chrono>
using std::vector;
using namespace std::chrono;
int main()
{
auto start = high_resolution_clock::now();
const vector<int> p{ 2,3,5 };
vector<int> idx{ 0,0,0 };
vector<int> num = { 2,3,4,5 }; num.reserve(1500);
vector<int> candidate(3);
while (num.size() < 1500) {
int candidate = INT_MAX;
for (int i = 0; i < p.size(); i++) {
int t;
while (num.back() >= (t=num[idx[i]] * p[i])) idx[i]++;
candidate = std::min(candidate, t);
}
num.push_back(candidate);
}
auto stop = high_resolution_clock::now();
auto duration = duration_cast<microseconds>(stop - start);
std::cout << num.back();
std::cout <<"ntakes "<< duration.count() << " microseconds";
}
代码可以进一步改进。想法是一样的,但通过记住候选数组[3]中的乘法结果,执行的乘法次数减少了:
const vector<int> p{ 2,3,5 };
vector<int> idx{ 1,0,0 };
vector<int> num = { 2,3,4,5 }; num.reserve(1500);
vector<int> candidate{ 6,6,10 };
while (num.size() < 1500) {
auto it = std::min_element(candidate.begin(), candidate.end());
if (num.back() != *it) num.push_back(*it);
int which_p = it - candidate.begin();
*it = num[++idx[which_p]] * p[which_p];
}
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 运行同一解决方案的另一个项目的项目
- 挂起和取消挂起一个文件DLL
- 用C++中的一个变量定义一个常量
- 函数向量_指针有不同的原型,我可以构建一个吗
- 在c++中用vector填充一个简单的动态数组
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 预处理器:插入结构名称中的前一个行号
- 我在c++代码中生成了一个运行时#3异常
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 从链接列表c++中删除一个项目
- 根据另一个数字的可整除性返回子数组中的索引
- 如何使用switch语句(C++)测试一个数字是素数还是可被7整除
- 创建一个程序来告诉用户一个数字是否可以被 5 整除
- 随机生成一个能被N整除的数的最佳算法
- 是否有可能编写一个函数模板来返回参数的数量是否能被N整除?
- 算出一个很大的数是否能被另一个数整除
- 如何在c++中检查一个数字是否可以被2*M_PI整除