GDUT寒假训练场4-Prime Distance

题目描述

The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number theoreticians for thousands of years is the question of primality. A prime number is a number that is has no proper factors (it is only evenly divisible by 1 and itself). The first prime numbers are 2,3,5,7 but they quickly become less frequent. One of the interesting questions is how dense they are in various ranges. Adjacent primes are two numbers that are both primes, but there are no other prime numbers between the adjacent primes. For example, 2,3 are the only adjacent primes that are also adjacent numbers.
Your program is given 2 numbers: L and U (1<=L< U<=2,147,483,647), and you are to find the two adjacent primes C1 and C2 (L<=C1< C2<=U) that are closest (i.e. C2-C1 is the minimum). If there are other pairs that are the same distance apart, use the first pair. You are also to find the two adjacent primes D1 and D2 (L<=D1< D2<=U) where D1 and D2 are as distant from each other as possible (again choosing the first pair if there is a tie).

输入格式

Each line of input will contain two positive integers, L and U, with L < U. The difference between L and U will not exceed 1,000,000.

输出格式

For each L and U, the output will either be the statement that there are no adjacent primes (because there are less than two primes between the two given numbers) or a line giving the two pairs of adjacent primes.

输入样例

2 17
14 17


输出样例

2,3 are closest, 7,11 are most distant.
There are no adjacent primes.

参考思路

题目大意是给定区间范围,分别找到两个距离最小和距离最大的素数。

我们用素数筛的话开不了这么大的数组,但题目暗示我们区间范围是不超过1000000的。那么我们可以

  • 筛出1-50000中的所有质数,并且对合数打上标记.
  • 在L-R的范围用我们已求出的质数筛出其中的合数(设p为质数,则i*p一定不为质数),并对其打上标记
  • 遍历L-R,没有打标记的元素即为我们所求的素数,然后存进另一个数组里即可。具体操作看代码。

 参考代码

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<memory>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 50;
ll l, r;
ll prime[maxn], cnt;
ll vis[maxn];//标记数组
ll p[maxn];//区间素数

void Gprime(ll n)//线性筛素数
{
    for (int i = 2; i <= n; ++i)
    {
        if (!vis[i])prime[++cnt] = i;
        for (int j = 1; i * prime[j] <= n && j <= cnt; j++)
        {
            vis[i * prime[j]] = 1;//标记合数
            if (i % prime[j] == 0) break;
        }
    }
}
int main()
{
    Gprime(50050);//筛出根号R内的所有质数以及剩下的合数
    while (scanf("%lld%lld", &l, &r)!=EOF)
    {
        l = l == 1 ? 2 : l;//特判L=1的情况
        memset(vis, 0, sizeof(vis));//重置标记数组,等下用来筛L R的素数

        for (ll i = 1; i <= cnt; ++i)//枚举已经筛出来的质数
        {
            ll p = prime[i];
            ll start;
            //我们从大于L的最小的能被p整除的数开始,因为有可能会在接下来筛的过程中把自己也一起筛掉,所以在此特判一下
            if ((l + p - 1) / p * p > 2 * p)
                start = (l + p - 1) / p * p;
            else
                start = 2 * p;

            for (ll j = start; j <= r; j += p)
                vis[j - l + 1] = 1;//因为如果从j开始标记的话可能会爆vis的空间,所以我们这里从1开始标记合数,类似滚动数组
        }

        ll count = 0;
        for (ll i = l; i <= r; ++i) //p为范围内素数 i要long long
        {
            if (!vis[i - l + 1])
                p[++count] = i;
        }

        if (count < 2)
            cout << "There are no adjacent primes.\n";
        else
        {
            ll m1 = p[1], m2 = p[2], n1 = p[1], n2 = p[2];
            for (ll i = 3; i <= count; ++i)
            {
                if (p[i] - p[i - 1] < m2 - m1)
                    m2 = p[i], m1 = p[i - 1];
                if (p[i] - p[i - 1] > n2 - n1)
                    n2 = p[i], n1 = p[i - 1];
            }
            printf("%lld,%lld are closest, %lld,%lld are most distant.\n", m1, m2, n1, n2);
        }
    }

   

    return 0;
}

昨夜雨疏风骤

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值