费尔马二平方素数

medie2005 2006-05-19 08:51:23
加精
题目:

除了2这个特别的素数外,所有的素数都可以分成两类:第一类是被4除余
1的素数,如5,13,17,29,37,41;第二类是被4除余3的素数,如3,7,
11,19,23,31。第一类素数都能表示成两个整数的平方和(第二类不能),
例如:5=1*1+2*2、13=2*2+3*3、17=1*1+4*4、29=2*2+5*5...这就是著名的
费尔马“二平方”定理。有趣的是:上述等式右侧的数有的又恰恰是两个素
数的平方,如13、29,我们就把这样的素数叫作费尔马“二平方”素数,即
是如果一个素数能够表示成两个素数的平方和的形式,例如:F=X*X+Y*Y
(1),其中F、X、Y都是素数,它就是费尔马“二平方”素数。

请求出并打印40亿以内的所有的费尔马“二平方”素数。

我已经写了一个,要6秒左右,麻烦高手们想一个算法使运行时间小于1秒。
...全文
1805 15 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
medie2005 2006-05-22
  • 打赏
  • 举报
回复
谢谢!!
kingbo2006 2006-05-21
  • 打赏
  • 举报
回复
我的程序设计如下:
#include <iostream>
#include <stdlib.h>
#include <math.h>
#include <fstream.h>
#include <windows.h>
using namespace std;
const int IsSuXu(const int x)//判断x是不是素数;
{
unsigned __int64 result;
unsigned __int64 temp=0,k=3;
int mod=((x%2)!=0);
unsigned __int64 _End= (int)sqrt((double)x);
while(k<=_End&&(x%k)!=0&&mod)
{
if((k%3)==0&&(k!=3))
{
k+=2;
temp++;
}
else
{
k+=2;
temp++;
}
}
if(k>_End) result=1;
else result=0;
return result;
}
int main(int argc, char *argv[])
{
double time1,time2;
unsigned __int64 i=3,count1=1,temp=0,count2=0;
int SuXu[6337];
ofstream fout("out.txt");
time1=GetTickCount();
SuXu[0]=2;
while(i<=63245)
{
if((i%3)==0&&(i!=3))
{
i+=2;
temp++;
}
else
{
if(IsSuXu(i)){SuXu[count1]=i;count1++;}
i+=2;
temp++;
}
}
time2=GetTickCount();
cout<<(time2-time1)/1000.0<<" s"<<endl;
time1=GetTickCount();
for(i=1;i<6337;i++)
{
temp=SuXu[i];
int j=0;
while(j<=i&&(temp*temp+4)%SuXu[j]!=0)
j++;
if(j>i)
{
//cout<<temp<<"*"<<temp<<"+4="<<temp*temp+4<<endl;
fout<<temp<<"*"<<temp<<"+4="<<temp*temp+4<<endl;
count2++;
}
}

//cout<<Two_Power(100)<<endl;;
cout<<IsSuXu(63241)<<endl;
time2=GetTickCount();
cout<<"count1="<<count1<<endl;
cout<<"count2="<<count2<<endl;
cout<<(time2-time1)/1000.0<<" s"<<endl;
system("PAUSE");
return 0;
}
程序的结果如下:
费尔马二平方素数共计716个:
用时0.3s左右。
medie2005 2006-05-21
  • 打赏
  • 举报
回复
高手们,我的程序错在哪里?麻烦大家看看啊,解决后立即揭贴。

如下:

//计算4000000000以内的费尔马素数,用时6-7秒
#include<iostream>
#include<cmath>
#include<windows.h>
using namespace std;
int primelist[ 6300 ];
bool isprime(int n)
{
unsigned int i=0;
unsigned int sn=(int)sqrt(n);
for(;primelist[i]<sn+1;++i)
if(n%primelist[ i ]==0)
return false;
return true;
}
void bornprimelist()
{
primelist[ 0 ]=3;
unsigned int i,count=0;
int step=4;
for(i=5;i<62500;i+=step)
{
if(isprime(i))
count++,primelist[ count ]=i;
step=6-step;
}
}
int main()
{
unsigned int i;
cout<<"13==2*2+3*3"<<endl;
cout<<"29==2*2+5*5"<<endl;
int count=2;
int time=GetTickCount();
bornprimelist();
for(i=53;i<4000000000;i+=120)
{
double dt=sqrt(i-4);
if(dt==(int)dt)
if(isprime((int)dt))
if(isprime(i))
{
cout<<i<<"==2*2+"<<dt<<'*'<<dt<<endl;
count++;
}
}
cout<<"total :"<<count<<endl;
cout<<"Use time :"<<GetTickCount()-time<<"ms"<<endl;
return 1;
}







kingbo2006 2006-05-21
  • 打赏
  • 举报
回复
祝贺我们从不同的角度,解决了这样一个问题。以后多多合作!谢谢!
mmmcd 2006-05-21
  • 打赏
  • 举报
回复
改了一下,一开始不应把模4余3的素数去掉。
找到718个。(运行楼上的程序似乎也是找718个哦)

#include <iostream.h>
#include <fstream.h>
#include <windows.h>
const int N=63246;
bool nprime[N];
int prime[N],pl;
ofstream fout("out.txt");
void init()
{
int i,j;
for(i=2;i<N;i++){
if(nprime[i])
continue;
//if(i%4==1)
prime[pl++]=i;
for(j=i+i;j<N;j+=i){
nprime[j]=true;
}
}
}

void output(__int64 p){
if(p>=10)
output(p/10);
//cout<<(int)(p%10);
fout<<(int)(p%10);
}

int main()
{
int i,j,d,c=0;
int time1,time2;
__int64 p;
time1=GetTickCount();
init();
time2=GetTickCount();
cout<<"筛选素数法,用时:"<<(time2-time1)/1000.0<<"s"<<endl;
for(i=0;i<pl;i++){
p=d=prime[i];
p=p*p+4;
if(d<=251){
if(!nprime[p]){
//cout<<(int)p<<'='<<"2*2+"<<d<<'*'<<d<<endl;
fout<<(int)p<<'='<<"2*2+"<<d<<'*'<<d<<endl;
c++;
}
}else{
for(j=0;j<i;j++){
if(p%prime[j]==0)
break;
}
if(j>=i){
output(p);
//cout<<'='<<"2*2+"<<d<<'*'<<d<<endl;
fout<<'='<<"2*2+"<<d<<'*'<<d<<endl;
c++;
}
}
}
time2=GetTickCount();
cout<<"总用时:"<<(time2-time1)/1000.0<<"s"<<endl;
cout<<"找到"<<c<<"个"<<endl;
return 0;
}


我的机子比较高级一点,输出如下

筛选素数法,用时:0s
总用时:0.203s
找到718个
kingbo2006 2006-05-21
  • 打赏
  • 举报
回复
对于MMMCD的法,我也赞同。判断10万以内的的素数所费的时间要比10万以上的素数要费时。不信的话你可以做一下试验。大约要多费0.001~0.01S的时间,这样在比较的判断中就会产生很大时间。
mmmcd 2006-05-21
  • 打赏
  • 举报
回复
(4000000000-53)/120=33333332.9

而小于63245的素数只有 6337 个
mmmcd 2006-05-21
  • 打赏
  • 举报
回复
你的方法:for(i=53;i<4000000000;i+=120)//对于<4000000000的每个整数i,判断sqrt(i-4)是否素数;这个循环效率太低了

建议这样:对于<63246的每个素数i,判断i*i+4是否素数;

我们判断素数的方法一样,
但素数个数远远小于整数的个数,时间就相差在这里
mmmcd 2006-05-20
  • 打赏
  • 举报
回复
用上述想法实现的程序

找到368个

#include <iostream.h>
#include <fstream.h>
const int N=63246;
bool nprime[N];
int prime[N],pl;
ofstream fout("out.txt");
void init()
{
int i,j;
for(i=2;i<N;i++){
if(nprime[i])
continue;
if(i%4==1)
prime[pl++]=i;
for(j=i+i;j<N;j+=i){
nprime[j]=true;
}
}
}

void output(__int64 p){
if(p>=10)
output(p/10);
cout<<(int)(p%10);
fout<<(int)(p%10);
}

int main()
{
int i,j,d;
__int64 p;
init();
for(i=0;i<pl;i++){
p=d=prime[i];
p=p*p+4;
if(d<=251){
if(!nprime[p]){
cout<<(int)p<<'='<<"2*2+"<<d<<'*'<<d<<endl;
fout<<(int)p<<'='<<"2*2+"<<d<<'*'<<d<<endl;
}
}else{
for(j=0;j<i;j++){
if(p%prime[j]==0)
break;
}
if(j>=i){
output(p);
cout<<'='<<"2*2+"<<d<<'*'<<d<<endl;
fout<<'='<<"2*2+"<<d<<'*'<<d<<endl;
}
}
}
return 0;
}
kingbo2006 2006-05-20
  • 打赏
  • 举报
回复
质数除了2以外都是奇数,这样你可以缩小一半的搜索量啊
mathe 2006-05-20
  • 打赏
  • 举报
回复
需要注意的是上面乘法可能会溢出,所以要使用64位的整数,在Windows里面用__int64,在Linux里面用long long.
mathe 2006-05-20
  • 打赏
  • 举报
回复
计算a^b (mod q)的代码如下:
power_mod(int a, int b, int q){
int mul=a%q, result=1;
while(b){
if(b&1){
result*=mul;result%=q;
}
mul*=mul; mul%=q;
b>>=1;
}
return result;
}
mathe 2006-05-20
  • 打赏
  • 举报
回复
如果发现这样计算速度太慢,我们可以使用素数探测方法来加速。
比如对于q=p^2+4,q比较大时,
我们首先计算2^(q-1) (mod q),如果这个数字不是1,那么q肯定不是素数。
如果2^(q-1)(mod q)=1,那么我们无法判断,然后再使用前面较慢的方法。
mathe 2006-05-20
  • 打赏
  • 举报
回复
也就是说p^2+4=q
可以先找出所有小于63245=sqrt(4*10^9)的素数。
对于每个这样的奇素数p,计算p^2+4,然后我们需要判断p^2+4是否是素数。
如果这个数字小于63245,那么我们可以利用现成的表格判断,不然,可以用所有小于p的型如
4K+1的素数去除,如果都不能整除,那么p^2+4就是素数,输出
kingbo2006 2006-05-20
  • 打赏
  • 举报
回复
能把你程序贴出来看看吗
有趣的数论名题 作者:周从尧,余未 编著 出版时间:2012年版 内容简介   《有趣的数论名题》以数论领域几个非常有名的问题为纲,汇集了计算数论、计算技术、GIMPS计划的最新成果,综合历史人物趣闻、逸事、研究进展过程,通古今、揽中外,共雅俗。 目录 序 前言 1 华林问题简介 1.1 引 言 1.2 定理及其证明 1.3 华林问题简介 1.4 相关定理及猜想 2 永垂不朽的正十七边形 2.1 引 言 2.2 正十七边形的代数知识 2.3 正十七边形的作图 2.4 证 明 2.5 更简捷的作法 2.6 后续 3 代数方程与超新星伽罗华 3.1 引 言 3.2 代数方程的求解 3.3 群星灿烂 3.4 拉格朗日预解式 3.5 伽罗华预解形与伽罗华群 3.6 结语 4 梅森素数:数学海洋中的璀璨明珠 4.1 由 来 4.2 梅森素数的意义和价值 4.3 历史的艰辛与趣闻 4.4 周海中猜想 4.5 未来之路 4.6 其他 5 费尔马大定理 5.1 费尔马大定理的由来 5.2 艰难的历史过程 5.3 最后的冲刺 5.4 费尔马定理证明的巨大意义 5.5 相关的定理和证明 6 费尔马数的趣闻 6.1 历史回顾 6.2 费尔马数猜想,费尔马大师也出错 6.3 费尔马数研究的回顾与现状 6.4 费尔马数因子网络搜寻计划 6.5 广义费尔马数 6.6 在发现或验证费尔马数方面所所用到的部分工具 6.7 后 续 7 有趣的谢尔宾斯基数 7.1 引 言 7.2 谢尔宾斯基数 7.3 谢尔宾斯基数问题 7.4 本书作者的两个证明 8 神奇的3x+l问题 8.1 引 言 8.2 引论和定义 8.3 Terras定理 9 黎曼猜想及黎曼零点计算 9.1 准备知识 9.2 问题的由来 9.3 黎曼手稿 9.4 零点计算的历程 9.5 更加艰难的证明历程 9.6 黎曼猜想的未来 9.7 相关方程及程序 10 其他有趣问题 10.1 欧几里德素数 10.2 福琼猜想 10.3 阶乘素数Nn=n!+l或Mn=m!-1 10.4 普罗斯素数 10.5 卡伦素数 10.6 沙马云达基一韦伦素数 10.7 奇完美数 10.8 卡迈克数 10.9 雷塞尔(Riesel)数 10.10 重一数猜想 10.11 孪生素数 10.12 陈素数 10.13 胡道尔(Woodall)素数 10.14 马尔科夫素数 附 录 01 费尔马数F。是合数的证明程序 02 梅森素数Ms:。是素数的证明程序 03 普罗斯数N=K*2n+1是素数的证明程序 04 生成108以内的素数表的程序 05 华林问题中生成n=1~50009范围内的g(4)的值的程序 06重一数是否是素数的证明程序 07 中国同余定理的计算例题程序 08 3x+1问题的计算程序 09 梅森数的分解程序 10 本书作者解决的费尔马直角三角形问题求解 11 FFT在大数乘法中的应用 参考文献

33,027

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧