AcWing 196. 质数距离

原题链接

考察:质数筛

一开始是在POJ上做的,感谢AcWing让我看到错误数据555

思路:

         朴素筛肯定不行.但这道题数字范围很大以至于数字难以用数组存储.好在题目提示r与l的范围差不超过1000000.这样可以将数组下标偏移,这样就能利用筛法求区间素数

          这道题要求出质数距离,也就是我们需要先求出范围内的素数.考虑到是多组输入.我们利用筛法筛掉合数是利用合数的最小质因数.所以我们可以预处理INT_MAX范围内的最小质因数.朴素筛法说明最小质因数不会超过√INT_MAX.我们预处理这部分的质因数即可

           接下来是利用质因数筛掉l,r范围内的合数.利用埃氏筛法即可

易错:

         注意l,r虽然都在int范围内,但必须声明为ll类型.否则埃氏筛的时候j<=r会RE

         l==1的时候需要特判,否则1也会被记录

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 const int N = 1000010,M = 50000;
 6 typedef pair<int,int> pii;
 7 typedef long long ll;
 8 int prime[M],cnt,ans[N],k;
 9 bool st[M],vis[N];
10 long long l,r;
11 void inits()
12 {
13     memset(vis,0,sizeof vis); k = 0;
14 }
15 void GetPrime(int n)
16 {
17     for(int i=2;i<=n;i++)
18     {
19         if(!st[i]) prime[++cnt] = i;
20         for(int j=1;prime[j]<=n/i;j++)
21         {
22             st[i*prime[j]] = 1;
23             if(i%prime[j]==0) break;
24         }
25     }
26 }
27 void Getans()
28 {
29     for(ll i=l;i<=r;i++)//r在int边界,i+1刚好越界 
30         if(!vis[i-l]) ans[k++] = i;
31 }
32 int main()
33 {
34 //    freopen("in.txt","r",stdin);
35     GetPrime(48500);
36     while(scanf("%lld%lld",&l,&r)!=EOF)
37     {
38         inits();
39         pii p[2];
40         int minv = 0x3f3f3f3f,maxn = -1;
41         for(int i=1;i<=cnt;i++)
42         {
43             for(ll j=max(2ll,(ll)(l+prime[i]-1)/prime[i])*prime[i];j<=r;j+=prime[i])
44                 vis[j-l] = 1;
45         }
46         if(l==1) vis[0] = 1;
47         Getans();
48         for(int i=0;i<k;i++)
49         {
50             if(i&&ans[i]-ans[i-1]<minv)
51             {
52                 minv = ans[i]-ans[i-1];
53                 p[0].first = ans[i-1],p[0].second = ans[i];
54             }
55             if(i&&ans[i]-ans[i-1]>maxn)
56             {
57                 maxn = ans[i]-ans[i-1];
58                 p[1].first = ans[i-1],p[1].second = ans[i];
59             }
60         }
61         if(k<=1) puts("There are no adjacent primes.");
62         else{
63             printf("%d,%d are closest, %d,%d are most distant.\n",p[0].first,p[0].second,p[1].first,p[1].second);
64         }
65     }
66     return 0;
67 }

 

2021.01.24 把代码换成了再写一遍的代码

有几个错误还是犯了:

  1. l=1的特例,脑子记得但处理还是处理错了,不能在inits()里直接初始化,这样会导致如果l为质数就会错误
  2. 大数据还是段错误了,原因在注释里标明了,数据在范围边界来回试探的变量直接开long long

 

posted @ 2021-01-15 14:34  acmloser  阅读(82)  评论(0编辑  收藏  举报