1.素数
素数定理: 随着x增长,π(x)/ ( x / ln x ) = 1
推论: pn是第n个素数,pn ~ n / ln n
伯兰特猜想:对于任意给定的正整数n,其中n>1,存在一个素数p,使得n<p<2*n
孪生素数猜想:存在无穷多的形如p和p+2的素数对
哥德巴赫猜想:大于2的正偶数可以表示成两个素数之和
n^2+1猜想:存在无穷多个形如n^2+1的素数
素数分布的应用:(素数定理)
http://acm.nefu.edu.cn/JudgeOnline/problem/117.jsp
这个题的话,书上的代码有些累赘,思路是一样的
求的是10^n以内的素数的个数的位数,先用素数定理求个数,然后对10取对数取整加1
#include <stdio.h>
#include <math.h>
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
double m;
m=double(n-log10(n)-log10(log(10)));
n=int(m)+1;
printf("%d\n",n);
}
return 0;
}
水题,先素数打表,然后判断
#include <stdio.h>
#include <string.h>
const int N=16777220;
int prime[N];
void Prime(int n)
{
memset(prime,0,sizeof(prime));
prime[1]=1;prime[0]=1;
for(int i=2;i*i<=n;i++)
if(prime[i]==0)
for(int j=2*i;j<=n;j+=i)
prime[j]=1;
}
int main()
{
int n;
Prime(N);
int t;
while(scanf("%d",&n)!=EOF)
{
t=0;
for(int i=2;i<n/2+1;i++)
if(!prime[i]&&!prime[n-i])
t++;
printf("%d\n",t);
}
return 0;
}
2.素数测试
[1]埃拉斯托尼斯筛法:
代码实现:
bool prime[N];
void Prime(int n)
{
memset(prime,true,sizeof(prime));
prime[1]=0;prime[0]=0;
for(int i=2;i*i<=n;i++)
if(prime[i])
for(int j=2*i;j<=n;j+=i)
prime[j]=0;
}
内循环是2,外循环是3,筛选次数减少,效率提高
代码实现:
// 6N+1法 筛选次数大大减少,但是感觉一般,效率一般
int prime[max],n=0;
bool isprime(int n)
{
if(n==2)
return true;
if(n%2==0)
return false;
for(int i=3;i*i<=n;i+=2)
if(!(n%i))
return false;
return true;
}
void Prime()
{
for(int i=1;i<=max;i+=3)
for(int j=0;j<2;j++)
if(isprime(2*(i+j)-1))
prime[n++]=2*(i+j)-1;
}
水题....感觉跟前面那个没什么两样
#include <stdio.h>
#include <string.h>
#define N 10000
bool prime[N];
void Prime(int n)
{
memset(prime,true,sizeof(prime));
prime[0]=0;
prime[1]=0;
for(int i=2;i*i<=n;i++)
if(prime[i]==1)
for(int j=2*i;j<=n;j+=i)
prime[j]=0;
}
int main()
{
Prime(N);
int n;
while(scanf("%d",&n)!=EOF,n!=0)
{
int t=0;
for(int i=2;i<n/2;i++)
if(prime[i]&′[n-i])
t++;
printf("%d\n",t);
}
return 0;
}
水题:
#include <stdio.h>
#include <string.h>
#define N 10010
bool prime[N];
void Prime()
{
memset(prime,1,sizeof(prime));
prime[0]=prime[1]=0;
for(int i=2;i*i<=N;i++)
if(prime[i])
for(int j=2*i;j<=N;j+=i)
prime[j]=0;
}
int main()
{
Prime();
int n;
while(scanf("%d",&n)!=EOF)
{
if(prime[n]==1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
终于不是水题了.....但是卡住了,尼玛...数量级21亿
分区筛选:
#include <stdio.h>
#include <string.h>
#define maxn 1000005
int prime[maxn];
int cnt[maxn];
int main()
{
int l,r;
__int64 i,j;
while(scanf("%d%d",&l,&r)!=EOF)
{
memset(prime,1,sizeof(prime));
if(l==1)
l=2;
for(i=2;i*i<=r;i++)
{
j=l/i*i;
if(j<i*i) j=i*i;
if(j<l) j+=i;
for(;j<=r;j+=i)
prime[j-l]=0;
}
int c=0;
for(i=l;i<=r;i++)
if(prime[i-l])
cnt[c++]=i;
if(c<=1)
{
printf("There are no adjacent primes.\n");
continue;
}
int mm=-1,nn=1000000000;
int sm,sn;
for(i=1;i<c;i++)
{
if(cnt[i]-cnt[i-1]>mm)
{
mm=cnt[i]-cnt[i-1];
sm=i;
}
if(cnt[i]-cnt[i-1]<nn)
{
nn=cnt[i]-cnt[i-1];
sn=i;
}
}
printf("%d,%d are closest, %d,%d are most distant.\n",cnt[sn-1],cnt[sn],cnt[sm-1],cnt[sm]);
}
return 0;
}
4.算数基本定理
max(gcd(a,b))+min(gcd(a,b))=a+b
n!的素因子分解中素数p的幂为: [n/p]+[n/p^2]+[n/p^3]+……
http://acm.nefu.edu.cn/JudgeOnline/problem/118.jsp
这个题由于是讨论0的数,也就是讨论10的因子的幂,阶乘数中2的幂大于5的幂,所以直接求5的幂是多少就是了
水题
#include <stdio.h>
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n;
scanf("%d",&n);
int sum=0,t=5;
while(n>=t)
{
sum+=n/t;
t*=5;
}
printf("%d\n",sum);
}
return 0;
}
水题
好吧 我是看了公式的 不然不敢说水
C(2n,n)恰好被p整除的次数由该公式表示:
([ 2n / p ] - 2 [ n / p ] )+ ( [ 2n / p ^ 2 ] - 2 [ n / p ^ 2 ] ) + …… + ( [ 2n / p ^ t ] - 2 [ n / p ^ t ] )
其中 t = [ log p ( 2n ) ]
#include <stdio.h>
#include <math.h>
int main()
{
int T,n,p;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&p);
double t=(log10(2.0*n)/log10(p));
int sum=0;
int tag=1;
for(int i=1;i<=t;i++)
{
tag*=p;
sum+=(int)(2*n/tag)-2*(int)(n/tag);
}
printf("%d\n",sum);
}
return 0;
}
4.梅森素数
http://imgsrc.baidu.com/forum/pic/item/a5c27d1ed21b0ef416056af8ddc451da80cb3ea2.jpg
n是素数,Mn= 2 ^ n - 1 称为第n个梅森数,可以是素数,也可以是合数
p是素数,Mp= 2 ^ p - 1 也是素数,Mp是梅森素数
梅森素数的判定:
(1) Lucas-Lehmer 判定法:电脑不好敲,还是给个链接吧 http://mathworld.wolfram.com/Lucas-LehmerTest.html
(2) Miller 素数测试法 : 不是人做的东西,主要思想:费马小定理
费马小定理:假如p是质数,且(a,p)=1,那么 a^(p-1) ≡1(mod p) 假如p是质数,且a,p互质,那么 a的(p-1)次方除以p的余数恒等于1
http://acm.nefu.edu.cn/JudgeOnline/problem/120.jsp
先看下关于 Lucas—Lehmer的一些证明,了解一下这个检测法
http://www.cqvip.com/Read/Read.aspx?id=20141190
这个题用筛法应该是过不了的,所以看看新方法
//这个代码有点问题
//我已经跟书的作者联系了
//以后再过来改吧,看懂的通知可以吱一声
#include <stdio.h>
#include <iostream>
#include <cstdlib>
using namespace std;
long long multi(long long a,long long b,long long m)
{
long long ret=0;
while(b>0)
{
if(b&1)
ret=(ret+a)%m;
b>>1;
a=(a<<1)%m;
}
return ret;
}
int main()
{
long long sum=1,data[66],tmp;
int n,p;
data[1]=4;
cin>>n;
while(n--)
{
sum=1;
cin>>p;
sum<<p;
sum-=1;
printf("%lld\n",sum);
for(int i=2;i<=p-1;i++)
{
tmp=multi(data[i-1],data[i-1],sum);
data[i]=(tmp-2)%sum;
}
if(p==2)
cout<<"yes"<<endl;
else
cout<<"no"<<endl;
}
return 0;
}
然后书上陈列了一个貌似又是错的代码,反正不简单,但是是一种必须掌握的素数测试算法,暂时先放放,有时间再回来看看
有谁闲得跑去AC了记得把把代码附上注释发我咯...
这章书上就写了这么多了.....然后我在网上看到了些比较好的资料,分享下:
主要是素数筛法 http://wenku.baidu.com/view/ab5139697e21af45b307a812.html
讲了fermat定理,素数判断等 http://wenku.baidu.com/view/4a1f5cfc910ef12d2af9e7a5.html### (强烈推荐)
关于梅森素数,我觉得这个总结得很好 http://blog.youkuaiyun.com/pinkcc/article/details/1393144
其中求梅森素数的代码
#include <iostream>
#include <cmath>
using namespace std;
__int64 prime[1000];
bool Int64_cout( __int64 lgint ) //带符号64位整数输出
{
char temp[24];
int j=0;
if(lgint<0)
{
cout<<'-';
lgint=-lgint;
}
else if(lgint==0)
{
cout<<'0';
return false;
}
while(lgint!=0)
{
temp[j++]='0'+lgint%10;
lgint/=10;
}
while(--j>=0)
cout<<temp[j];
return true;
}
bool MCN(int mersenneCN)
{
__int64 ans=1,j,temp,t2,t3;
int i,k=0,l;
double st,temp2;
for(i=0;i<mersenneCN;i++)
ans*=2;
ans--;
//Int64_cout(ans);
//cout<<endl;
temp=ans;
temp2=temp;
st=sqrt(temp2);
for(j=1;temp>1;j++)
{
t2=6*j-1;
t3=6*j+1;
if(temp%t2==0)
{
prime[k++]=t2;
temp/=t2;
temp2=temp;
st=sqrt(temp2);
//Int64_cout(prime[k-1]);
//cout<<endl;
}
if(temp%t3==0)
{
prime[k++]=t3;
temp/=t3;
temp2=temp;
st=sqrt(temp2);
//Int64_cout(prime[k-1]);
//cout<<endl;
}
if(st<=t2)
{
prime[k++]=temp;
break;
}
}
for(l=0;l<(k-1);l++)
{
Int64_cout(prime[l]);
cout<<" * ";
}
Int64_cout(prime[l]);
cout<<" = ";
Int64_cout(ans);
cout<<" = ( 2 ^ "<<mersenneCN<<" ) - 1"<<endl;
return true;
}
int main()
{
int MaxN;
cin>>MaxN;
int mersenneCN[9]={11,23,29,37,41,43,47,53,59};
int i;
for(i=0;i<9;i++)
{
if(mersenneCN[i]<=MaxN)
{
MCN(mersenneCN[i]);
}
else
break;
}
return 0;
}
本文深入讲解素数的各种性质和测试方法,包括素数定理、哥德巴赫猜想、孪生素数猜想等,并介绍了埃拉斯托塞尼筛法、6N+1法等多种高效筛选素数的方法。
3873

被折叠的 条评论
为什么被折叠?



