求小于N的素数解决方案
求小于N的素数
最近写了个求小于N的素数的程序,感觉效率一般。在i3处理器上求小于100万的素数15秒,小于1千万的素数要5分钟。哪位大神帮改进一下,或者有什么更效率的算法,指点一下。
下面是源代码:
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <time.h>
typedef unsigned long long ULL;
using namespace std;
int main(int args, char *argv[])
{
clock_t start, finish;
double time;
unsigned long long m, n, i;
short f = 1;
vector<ULL> prime;
vector<ULL>::iterator p;
prime.push_back(2);
cin >> n;
i = 3;
start = clock();
while (i <= n)
{
f = 1;
m = sqrtl(i);
for (p = prime.begin(); *p <= m; p++)
{
if(0 == i % *p)
{
f = 0;
break;
}
}
if (0 == f)
{
f = 1;
i += 2;
}
else
{
prime.push_back(i);
i += 2;
}
}
finish = clock();
time = (double)(finish - start) / CLOCKS_PER_SEC;
//for(p = prime.begin(); p != prime.end(); p++)
//{
// cout << *p << "\n";
//}
cout << endl;
cout << prime.size() << endl;
cout << time << endl;
return 0;
}
------解决方案--------------------
是什么原因? 就因为我的是i7的Mac? 1000w,我才5.26366秒啊。
就是你的代码。
------解决方案--------------------
更效率的算法
--------------
1.以空间换时间
2.WitNess算法,判断素数
------解决方案--------------------
你可以研究一下欧拉筛法
------解决方案--------------------
http://blog.****.net/creazierhit/article/details/7792571
楼主看看这个,我也是别人那儿找的,挺好的所以收藏啦!
------解决方案--------------------
------解决方案--------------------
百度 Miller-Robbin 素数测试算法。 目前最快的素数测试算法, 基于概率论 和 佛洛依德生日悖论的 因子碰撞思想, 暴力破解密码的 基础算法之一。。。
------解决方案--------------------
------解决方案--------------------
对于一个输入N, 计算是否为素数的代码。。。 然后你可以吧其中计算过程提取出来放到你的0-N的循环中, 然后比较一下1000w的运行时间,, 看看能否赶上他的I7, 看看 数学算法能否 战胜 硬件???
拭目以待,,,
最近写了个求小于N的素数的程序,感觉效率一般。在i3处理器上求小于100万的素数15秒,小于1千万的素数要5分钟。哪位大神帮改进一下,或者有什么更效率的算法,指点一下。
下面是源代码:
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <stdlib.h>
#include <vector>
#include <time.h>
typedef unsigned long long ULL;
using namespace std;
int main(int args, char *argv[])
{
clock_t start, finish;
double time;
unsigned long long m, n, i;
short f = 1;
vector<ULL> prime;
vector<ULL>::iterator p;
prime.push_back(2);
cin >> n;
i = 3;
start = clock();
while (i <= n)
{
f = 1;
m = sqrtl(i);
for (p = prime.begin(); *p <= m; p++)
{
if(0 == i % *p)
{
f = 0;
break;
}
}
if (0 == f)
{
f = 1;
i += 2;
}
else
{
prime.push_back(i);
i += 2;
}
}
finish = clock();
time = (double)(finish - start) / CLOCKS_PER_SEC;
//for(p = prime.begin(); p != prime.end(); p++)
//{
// cout << *p << "\n";
//}
cout << endl;
cout << prime.size() << endl;
cout << time << endl;
return 0;
}
------解决方案--------------------
是什么原因? 就因为我的是i7的Mac? 1000w,我才5.26366秒啊。
就是你的代码。
------解决方案--------------------
更效率的算法
--------------
1.以空间换时间
2.WitNess算法,判断素数
------解决方案--------------------
你可以研究一下欧拉筛法
------解决方案--------------------
http://blog.****.net/creazierhit/article/details/7792571
楼主看看这个,我也是别人那儿找的,挺好的所以收藏啦!
------解决方案--------------------
------解决方案--------------------
百度 Miller-Robbin 素数测试算法。 目前最快的素数测试算法, 基于概率论 和 佛洛依德生日悖论的 因子碰撞思想, 暴力破解密码的 基础算法之一。。。
------解决方案--------------------
------解决方案--------------------
对于一个输入N, 计算是否为素数的代码。。。 然后你可以吧其中计算过程提取出来放到你的0-N的循环中, 然后比较一下1000w的运行时间,, 看看能否赶上他的I7, 看看 数学算法能否 战胜 硬件???
拭目以待,,,
- C/C++ code
#include <iostream> #include <stdlib.h> #include <time.h> #include <math.h> using namespace std; typedef unsigned long long TYPE; // 产生随机数 static bool bInitRandom = false; TYPE GetRandomi(TYPE Begin, TYPE End) { if (!bInitRandom) { bInitRandom = true; srand((unsigned int) time(NULL)); } return Begin + rand() % (End - Begin); } // a*b % n求模 TYPE MultiplyMod(TYPE a, TYPE b, TYPE n) { TYPE nReturn = 0 , i ; a %= n; b %= n; for (i = b; i > 0; a = (a << 1) % n, i >>= 1) { if (i & 1) { nReturn = (nReturn + a) % n; } } return nReturn; } // 获取2进制序列 int GetBinarySet(bool* pBinarySet, TYPE nNum) { int nLen = 0; while(nNum) { pBinarySet[nLen ++] = nNum & 1; nNum >>= 1; } return nLen; } // 如果结果不为1,则一定是合数,如果结果为1,可能为素数 TYPE ModularExponetiation(TYPE bigDigit, TYPE b, TYPE n) { // 整形变量最多32位,所以可以用32字节存储2进制串, nLen存储长度 TYPE nReturn = 1; int nLen = 0; bool szbBinarySet[64] = { 0 }; // 获取b的二进制串 nLen = GetBinarySet(szbBinarySet, b); for (int i = nLen - 1; i >= 0; i --) { nReturn = MultiplyMod(nReturn, nReturn , n); //nReturn = nReturn * nReturn % n; if (szbBinarySet[i]) { nReturn = MultiplyMod(nReturn, bigDigit, n); //nReturn = nReturn * bigDigit % n; } } return nReturn; } bool Witness(TYPE bigDigit, TYPE n) { TYPE u = 0, t = 0, x, y, i; // 初始化 u,t // 产生一个奇数u,使得 n - 1 == 2^t * u, t >= 1 int nLen = 0; TYPE tmp = n - 1; while(tmp) { nLen ++; tmp >>= 1; } for (t = nLen -1; t >= 0; t --) { i = 1; for(int j = 0; j < t; j ++) { i <<= 1; } if ((n - 1) % i == 0 ) // 若 n -1可以整除 2^t { u = (n - 1) / i; // 如果u是奇数则停止 if(u % 2 == 1) { break; } } } x = ModularExponetiation(bigDigit, u, n); // 测试 x是否为伪素数 for (i = 0; i <= t; i ++) { y = MultiplyMod(x, x, n); //y = x * x % n; if (x == 1 && y != 1 && y != n -1) { return true; } x = y; } if (x != 1) { return true; } return false; } bool MillerRabin(TYPE llValue, int nTime) { for(int i = 0; i < nTime; i ++) { TYPE a = GetRandomi(1, llValue - 1); //a = 20280; if(Witness(a, llValue)) return false; // 肯定是合数 } return true; // 可能是素数 } int main() { int n; cin >> n; TYPE llValue; bool* pIsPrim = new bool[n]; memset(pIsPrim, 0, sizeof(bool) * n); for(int i = 0; i < n; i ++) { cin >> llValue; if (llValue == 2) { pIsPrim[i] = true; continue; } else { if(MillerRabin(llValue, 10)) // 10次蒙特卡洛算法,正确率在99%以上 { pIsPrim[i] = true; } } } for(int i = 0; i < n; i ++) { if(pIsPrim[i]) { cout << "Yes" << endl; } else { cout << "No" << endl; } } delete[] pIsPrim; return 0; }