【大区间质数 合数标记】 prime distance

传送门

题意

给定两个整数\(l,r\),求在\([l,r]\)区间内距离最近的一对相邻质数,和距离最远的一对相邻质数

数据范围

\(l,r \in [1 , 2^{31}-1]\)

其中\(r-l \leq 10^{6}\)

题解

\(l,r\)的范围很大,大约是\(2\times 10^{9}\),线性算法也无法求出\([1,r]\)的所有质数,但是\(r-l\)的范围小,

通过\(x-l\)来映射\(l\sim r\)之间的每一个数字

任何一个合数必定会包含一个不超过 \(\sqrt{n}\)的质因数,所以求出 \(2\sim \sqrt{r}\) 的所有质数,

  • 对于每个质数,将\([l,r]\)中能整除这个数字的标记,剩下的就是区间内的质数。

    • 找到\(\geq l\)的关于\(p\)的倍数,即为\(\lceil \frac{L}{p}\rceil \times p\)

    • 在标记合数的时候需要取\(max(2\times p ,\lceil \frac{L}{p}\rceil \times p)\),因为\(p\)是素数不能被标记为合数

对于所有质数两两求距离,最后求最值即可

时间复杂度 :

  • $ = \sqrt{r} + (\frac{r-l}{2} + \frac{r-l}{3} + \dots + \frac{r-l}{r-l})$

  • \(=\sqrt{r} + (r-l) \times (\frac{1}{2} + \frac{1}{3} + \dots + \frac{1}{r})\)

    • \(\frac{1}{2} + \frac{1}{3} + \dots + \frac{1}{r-l}\approx log(log(r-l))\)

\(O (\sqrt{r} \times log (log (r-l)))\)

Code

#include<bits/stdc++.h>
using namespace std;
#define rep(i,a,n) for(int i=a;i<n;i++)
#define per(i,a,n) for(int i=n-1;i>=a;i--)
#define ll long long

const int N=1e6+10;

ll l,r;
int primes[N],cnt;
bool st[N];
bool f[N];
int ans[N];
void get_primes(int n)
{
    rep(i,2,n+1)
    {
        if(!st[i]) primes[++cnt]=i;
        for(int j=1;primes[j]<=n/i;j++)
        {
            st[primes[j]*i]=1;
            if(i%primes[j]==0) break;
        }
    }
}

void solve()
{
    get_primes(sqrt(r));
    memset(f,0,sizeof f);
    rep(i,1,cnt+1)
    {
        ll p=primes[i];

        // 求出 l~r关于当前素数的起点
        for(ll j=max(2*p,(l+p-1)/p * p);j<=r ;j+=p)
            f[j-l] = 1;
    }
    int num=0;
    rep(i,0,r-l+1)
    {
        if(!f[i] && i+l>1) // 特判1被标记的情况
            ans[++num] = i+l;
    }
    if(num<2) cout<<"There are no adjacent primes."<<endl;
    else 
    {
        int mx=1,mi=1;

        rep(i,1,num)
        {
            int dis=ans[i+1]-ans[i];
            if(dis>ans[mx+1]-ans[mx]) mx=i;
            if(dis<ans[mi+1]-ans[mi]) mi=i;
        }
        cout<<ans[mi]<<","<<ans[mi+1]<<" are closest, "<<ans[mx]<<","<<ans[mx+1]<<" are most distant."<<endl;
    }
}

int main()
{
    while(cin>>l>>r) solve();
}
posted @ 2020-10-23 17:33  Hyx'  阅读(141)  评论(0)    收藏  举报