ZCMU-1689: 找质数

点击打开链接

Description

质数(prime number)又称素数,有无限个。一个大于1的自然数,除了1和它本身外,不能被其他自然数整除,换句话说就是该数除了1和它本身以外不再有其他的因数;否则称为合数。

根据算术基本定理,每一个比1大的整数,要么本身是一个质数,要么可以写成一系列质数的乘积;而且如果不考虑这些质数在乘积中的顺序,那么写出来的形式是唯一的。最小的质数是2。

目前为止,人们未找到一个公式可求出所有质数。

这道题想要你找出从L到R的区间内的所有质数。为了简化输出,你只需输出给定区间内的所有质数的和。

Input

t测试的数据个数。t<=500

接下来每组测试数据,有两个自然数,L和R。2 <= L <= R <= 10^12-1, R-L <= 106

Output

对每组自然数的区间L,R。输出从L到R中所有质數的和。

Sample Input

3
2 10
3 7
1000000 2000000

Sample Output

17
15
105363426899


这题咋一眼看好像有点难的样子

虽然范围是10^12,但是R-L是10^6。我们用a【i】来表示i+L是否为素数。

首先查找出 1-10^6的所以素数。用这个素数来做标记。素数的倍数(大于1倍)都是合数。最后求和。

AC代码:

#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int size=1000010;
ll a[size],b[size],c[size],num;
void init()
{
     int i,j;
     num=0;
     for (i=2;i<1000010;i++)
     {
         if (a[i]==0) b[num++]=i;
         for (j=0;j<num&&i*b[j]<1000010;j++)
         {
             a[i*b[j]]=1;
             if (i%b[j]==0) break ;
         }
     }
}
int main(){
     init();
     int t;
     ll l,r,e,bb,j,i;
     scanf ( "%d" ,&t);
     while (t--)
     {
         scanf ( "%lld%lld" ,&l,&r);
         memset (c,0, sizeof (c));
         for (i=0;i<num;i++)
         {
             if (l%b[i]==0) bb=l/b[i];
             else bb=l/b[i]+1;
             e=r/b[i];
             if ( bb<2 ) bb=2;
             for (j=bb;j<=e;j++) c[b[i]*j-l]=1;
         }
         ll ans=0;
         for (i=0;i<=r-l;i++) if (!c[i]) ans+=i+l;
         cout<<ans<<endl;
     }
     return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_41713256/article/details/80465207