zoukankan      html  css  js  c++  java
  • 素数

     什么是素数就不用多说了吧~~


    素数定理:设小于正实数n的素数有f(n)个,f(n)≈n/ln(n)。

    推论:令pn是第n个素数,其中n是正整数,那么pn≈n×ln(n)。

    定理:对于任意的正整数n,至少存在n个连续的正合数。


    关于素数的猜想:

    1、伯特兰猜想:对于任意给定的正整数n,其中n>1,都存在一个素数p,使得n<p<2n。(切比雪夫已证明)

    2、孪生素数猜想:存在无穷多的形如p和p+2的素数对。(陈景润已证明)

    3、哥德巴赫猜想:每个大于2的正偶数都可以写成两个素数的和。(已验证所有小于4×1014的偶数都满足这个猜想)

    4、n2+1猜想:存在无穷多个形如n2+1的素数,其中n是正整数。


     素数测试:

    1、埃拉托色尼筛法

    基本素数判别法:正整数n是素数,当且尽当它不能被任何一个小于√n的素数整除。

    定理:如果n是一个合数,那么n一定有不超过√n的素因子。

     1 //pri[i]为0的i是素数
     2     int pri[maxn];
     3     memset(pri,0,sizeof(pri));
     4     pri[0]=pri[1]=1;
     5     for(int i=2;i*i<maxn;i++){
     6         if(!pri[i]){
     7             for(int j=i*i;j<maxn;j+=i){
     8                 pri[j]=1;
     9             }
    10         }
    11     }
    埃拉托色尼筛法

    2、6N+1法

    所有的素数都可以表示成6N±1的形式

     注:当n过大时,可以先求出小于√n的素数表,然后用基本素数判别法判断。

    例题 POJ - 2689

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 #define CLR(m,a) memset(m,a,sizeof(m))
     6 #define LL long long
     7 const int maxn=50010;
     8 const int inf=0x3f3f3f3f;
     9 int prepri[maxn],vis[maxn*20];
    10 int cnt=0;
    11 int pri[maxn*20];  //存L到R之间的素数
    12 
    13 void init()
    14 {
    15     CLR(vis,1);
    16     cnt=0;
    17     for(LL i=2;i<maxn;i++)if(vis[i]){
    18         prepri[cnt++]=i;
    19         for(LL j=i*i;j<maxn;j+=i) vis[j]=0;
    20     }
    21 }
    22 
    23 int main()
    24 {
    25     LL L,R;
    26     while(scanf("%lld%lld",&L,&R)!=EOF){
    27         init();
    28         CLR(vis,1); //假设全是素数
    29         for(int i=0;i<cnt;i++){
    30             LL b=L/prepri[i];
    31             while(b*prepri[i]<L||b<=1) b++;  //小于L的不用管
    32             for(LL j=b*prepri[i];j<=R;j+=prepri[i])if(j>=L){
    33                 vis[j-L]=0;
    34             }
    35             if(L==1) vis[0]=0;  //1不是素数
    36         }
    37         LL minn=inf,maxx=-inf;
    38         LL x1,y1,x2,y2;
    39         int prict=0;
    40         for(int i=0;i<=R-L;i++) if(vis[i])
    41             pri[prict++]=L+i;
    42         if(prict<=1) puts("There are no adjacent primes.");
    43         else {
    44             for(int i=1;i<prict;i++){
    45                 if(pri[i]-pri[i-1]<minn){
    46                     minn=pri[i]-pri[i-1];
    47                     x1=pri[i-1];y1=pri[i];
    48                 }
    49                 if(pri[i]-pri[i-1]>maxx){
    50                     maxx=pri[i]-pri[i-1];
    51                     x2=pri[i-1];y2=pri[i];
    52                 }
    53             }
    54             printf("%lld,%lld are closest, %lld,%lld are most distant.
    ",x1,y1,x2,y2);
    55         }
    56 
    57     }
    58     return 0;
    59 }
    基本素数判别法

    基本算术定理:

      每个大于1的正整数n都可以唯一地被写成素数的乘积,在乘积中的素因子按照非降序排列。

    性质:

      1、若n的标准素因子分解表达式为n=p1a1+p2a2+……+pnan  ,设d(n)为n的正因子个数,Φ(n)为n的所有因子之和

        则d(n)=(a1+1)×(a2+1)×……×(an+1),Φ(n)= 可以用数列求和公式

      2、n!的素因子分解中素数p的幂为[n/p]+[n/p2]+[n/p3]+……

    编辑公式好麻烦,就写这两个吧。。。

    例题nefu118,计算n!后面有多少个0。按照公式2,计算素数5的幂即可(因为2的幂一定大于5的幂)。

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 int main(){
     5     int m;
     6     scanf("%d",&m);
     7     while(m--){
     8         int n;
     9         scanf("%d",&n);
    10         int tmp=5;
    11         int ans=0;
    12         while(tmp<=n){
    13             ans=ans+n/tmp;
    14             tmp=tmp*5;
    15         }
    16         printf("%d
    ",ans);
    17     }
    18     return 0;
    19 }
    nefu 118

     例题nefu119,计算C(2n,n)被素数p整除多少次。(先把组合数公式写出来,然后和上题类似,分子分母分别计算,然后相减)


    还有梅森素数没写,等等~

  • 相关阅读:
    DropDownList 禁止选择某一项
    C语言文件操作函数(ANSI)详解(二)
    c语言中break与continue的区别
    指针函数
    C语言文件操作函数(ANSI)详解(一)
    结构体指针
    ASCII\UNICODE编码的区别
    函数调用二维数组例子
    getchar()函数getch()函数区别
    C语言 二维数组做函数参数的几种情况
  • 原文地址:https://www.cnblogs.com/yijiull/p/7242971.html
Copyright © 2011-2022 走看看