首页 > 代码库 > NOI 1.5 44:第n小的质数

NOI 1.5 44:第n小的质数

---恢复内容开始---

描述

输入一个正整数n,求第n小的质数。

输入
一个不超过10000的正整数n。
输出
第n小的质数。
样例输入
10
样例输出
29
    •  方法1:合数一定可以表示成一个比它小的质数的几倍,所以若一个数不能整除比它小的所有的质数,则这个数是质数。所以,若要找第n个质数,则可以第n-1个质数为起点开始,通过上述方法判断。
    •  
 1 #include<iostream>
 2 using namespace std;
 3 int n,s;
 4 int p[10001];
 5 int pan(int t)
 6 {
 7     while(1)
 8     {
 9         bool ok=0;
10         for(int i=1;i<=s;i++)//若它是质数,则不不能整除比它小的所有的质数 
11          if(t%p[i]==0) 
12          {
13              ok=1;break;
14          }
15         if(ok) 
16         {
17             t++;continue;
18         }
19         return t;
20     }
21 }
22 int main()
23 {
24     cin>>n;
25     p[1]=2;s++;//s表示当前质数数目 
26     for(int i=2;i<=n;i++)
27     {
28         int t=p[s]+1;//下一个质数的至少比上一个质数大1 
29         int h=pan(t);//确定下一个质数 
30         p[++s]=h;
31     }
32     cout<<p[n];
33 }

 

  •  方法2:是对方法1的改进,方法1中是判断不能整除所有比它小的质数,结合根号n复杂度判断质数的原理,例:15=3*5,枚举到3时判断了一次,5时又判断了一次,造成重复判断。所以判断能否整除比它小的所有的质数,仅需判断到根号n即可
  •  
  •  
    技术分享
    #include<cstdio>
    #include<cmath>
    using namespace std;
    int n,s;
    int p[100001];
    int devide(double k)
    {
        int x=(int)k;
        for(int i=1;i<s;i++)
        {
            if(p[i]>=x)
            return i+1;//因为开立方后的数k强制转化成了整数x,实际上x比k小了,所以要+1 
        }
    }
    int main()
    {
        scanf("%d",&n);
        p[1]=2;p[2]=3;
        s=2;
        while(s<n)
        {
            int tmp=p[s];//上一个质数 
            s++;//当前要找的是第s个质数 
            while(1)
            {
                tmp++;//至少比上一个质数大1 
                bool ok=false;
                int test=devide(sqrt(tmp));//找到要判断的数开平方后处于哪两个质数之间 
                for(int i=1;i<=test;i++) 
                 if(tmp%p[i]==0)
                 {
                     ok=true;
                     break;
                 }
                if(ok) continue;
                p[s]=tmp;
                break;  
            }
        }
        printf("%d",p[n]);
    }
    View Code

     

  •  

---恢复内容结束---

NOI 1.5 44:第n小的质数