uva_10140/poj_2689 Prime Distance(區間素數)

uva 題目鏈接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=35&page=show_problem&category=13&problem=1081&mosmsg=Submission+received+with+ID+15689014

題目大意:在給定範圍L和R,找到L和R範圍內差距最小和最大的兩對素數。1=< L<=R<=2,147,483,647,R-L<=1000000

分析:

區間素數,經典問題。因為最大是2^31-1,開根號為小於46341,所以可以先預處理做一遍素數篩選,篩出1~50000的素數,然後再用1~50000的素數去篩選任意L到R之間的素數。具體做法,可開一個a[]存所求區間的素數情況,求a[L]~a[R]之間的素數,就是求a[0]~a[R-L]之間的素數。

代碼:

#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
#define range 50000
#define range2 1000010
#define INF 0xFFFFFFF
typedef long long LL;
int prime[range],is_prime[range];
int a[range2],prime2[range2];
int num_p;
void produce_prime()
{
    memset(is_prime,0,sizeof(is_prime));
    num_p=0;
    for(int i=2;i<range;i++)
    {
        if(is_prime[i]==0)
        {
            int j=i+i;
            prime[num_p++]=i;
            while(j<range)
            {
                is_prime[j]=1;
                j+=i;
            }
        }
    }
}
int main()
{
//  freopen("in.txt","r",stdin);
    LL left,r;
    produce_prime();//預處理先篩出50000以內的素數
    while(scanf("%lld%lld",&left,&r)==2)//這裡如果用%d%d,在poj上會TLE,但是在uva上能AC
    {
        memset(a,0,sizeof(a));
        if(left==1)
        {
            a[0]=1;  //如果L=1,它不能算做素數,此處特判
        }
        for(int i=0;i<num_p && prime[i]*prime[i]<=r;i++)//從最小的素數開始,循環要小於素數個數和小於R的開根號
        {
            int k=(int)left/prime[i];//從prime[i]的倍數開始篩,並且這個倍數要大於等於left,k為prime[i]的幾倍
            LL m=k*prime[i];
            while(m<left || k<=1) //因為k是整除得來,所以如果left不是prime[i]的整數倍,多餘的部分就會被去掉,或者出現left<prime[i]的情況;還有就是正好left是素數,k=1,此時left不能被篩掉,所以要讓k>1而且m>=k
                {
                 m+=(LL)prime[i];
                 k++;
                }
            for(LL j=m;j<=r;j+=prime[i])
            {
                if(j>=left)//開始用素數篩,將left~r中prime[i]的倍數篩掉,因為left,r可能很大,這裡用了一個**偏移的index**的技巧,即a[j]=1等價于a[j-left]=1,篩選時將所有a[left]~a[r]==a[0]~a[r-left]
                    a[j-left]=1;
            }
        }
        int minn=INF,maxx=-1;
        int minflag=-1,minf=-1,minlast=-1,maxf=-1,maxlast=-1,pre=-1;
        for(LL i=left;i<=r;i++)
        {
            if(a[i-left]==0)//這裡一樣,也是用偏移index去判斷是否被篩出
            {
                if(pre==-1)
                    {
                     pre=i;
                    }
                    else
                    {
                        if(i-pre<minn)
                        {
                            minf=pre; minlast=i;
                            minn=i-pre;
                        }
                        if(i-pre>maxx)
                        {
                            maxf=pre; maxlast=i;
                            maxx=i-pre;
                        }
                        pre=i;
                    }
                //last=i;
            }
        }
        if(minf==-1)
            printf("There are no adjacent primes.\n");
            else
                printf("%d,%d are closest, %d,%d are most distant.\n",minf,minlast,maxf,maxlast);
    }
    return 0;
}

關於質數的一些重要結論:

設pi(n)為小於等於n的質數個數,則pi(n)\approxn/n/ln(n)

當n在10^5到10^6左右時,質數的數量大概可以用10/n來估計。

第 n 個質數大約是 nln(n)

《计算机算法导引: 设计与分析》有講到質數的這部分

另外一種求大範圍質數的方法:

http://www.jiancool.com/article/50042575894/

时间: 2024-11-01 13:54:50

uva_10140/poj_2689 Prime Distance(區間素數)的相关文章

[题解](区间质数筛)POJ_2689 Prime Distance

区间筛素数:先筛出1~sqrt(R)的素数,然后对于每个询问只要用这些素数筛掉区间内的合数即可. 几个细节:1.特判和1有关的一些情况 2.每次减去L偏移量,数组只开区间大小 3.POJ无法使用万能头文件(需要火星救援(大雾 #include<iostream> #include<cstdio> #include<cstring> using namespace std; int prime[50009]; bool ck[1000009],tmp[1000009];

樹狀數組區間操作模板

樹狀數組支持區間修改與區間查詢,很久沒編,又快忘了,編程時要注意的兩點是:1.樹狀數組前綴和可能會爆int 2.用%d讀入long long即使輸入數據保證小於10^9也可能出問題 記錄差分數組a[i]=num[i]-num[i-1]; sum[i]=sum[1]+sum[2]+...+sum[n]  =a1+a1+a2+a1+a2+a3+...+a1+a2+...+an  =n*a1+(n-1)*a2+...+1*an  =(n+1)*(a1+a2+...+an)-1*a1-2*a2-...-

[ACM] POJ 2689 Prime Distance (筛选范围大素数)

Prime Distance Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12811   Accepted: 3420 Description The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number th

UVA 10140 - Prime Distance(数论)

10140 - Prime Distance 题目链接 题意:求[l,r]区间内最近和最远的素数对. 思路:素数打表,打到sqrt(Max)即可,然后利用大的表去筛素数,由于[l, r]最多100W,所以可以去遍历一遍,找出答案.注意1的情况,一开始没判断1,结果WA了 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define INF 0x3f

POJ-2689 Prime Distance(线性筛法)

Prime Distance Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 17021   Accepted: 4536 Description The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number th

POJ 2689 Prime Distance 素数筛选法应用

题目来源:POJ 2689 Prime Distance 题意:给出一个区间L R 区间内的距离最远和最近的2个素数 并且是相邻的 R-L <= 1000000 但是L和R会很大 思路:一般素数筛选法是拿一个素数 然后它的2倍3倍4倍...都不是 然后这题可以直接从2的L/2倍开始它的L/2+1倍L/2+2倍...都不是素数 首先筛选出一些素数 然后在以这些素数为基础 在L-R上在筛一次因为 R-L <= 1000000 可以左移开一个1百万的数组 #include <cstdio>

POJ 2689 Prime Distance

Prime Distance Description 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

POJ题目2689 Prime Distance(任何区间素数筛选)

Prime Distance Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13459   Accepted: 3578 Description The branch of mathematics called number theory is about properties of numbers. One of the areas that has captured the interest of number th

poj 2689 Prime Distance 【数论】【筛法求素数】

题目链接:传送门 题目大意: 给你L和R两组数,L和R的范围是2^32,其间隔(即R-L最大为1,000,000.) .让你求出L和R之间素数的最大间隔和最小的间隔. 比如 2 17.之间的最小素数间隔是2 3,最大的素数间隔是11 17. 要是直接进行一个2^32次方筛法然后在判断是会T的. 我们这样来想,筛法求素数的原理是什么: /**vis数组标记为0则说明是素数*/ int vis[10005]; void getPrimevis(int n) { int m=sqrt(n+0.5);