大素数筛子

题目地址:http://acm.fafu.edu.cn/problem.php?id=1011

Description:

The problem is very simple,your job is just to calculate the sum of primes from the first prime to the Nth prime.

Input:

The input consists multiple cases. Each line contains a N(1<=N<=1000000).

Output:

For each N,output the result of this problem that describe before.

Sample Input:

1

3

5

Sample Output:

2

10

28

题目意思是说输入一个N,计算从第1个素数到第N个素数的和。注意看题目,N最大可能达到100万。也就是说测试数据有可能让你计算从第1个素数到第100万个素数的和。这题的难点在于如何快速筛选出素数。如果我们用枚举法(或普通的方法),那必定会超时。这里,我要介绍一个大素数筛子(专门筛选素数)。

我们知道2,5,7...这些都是素数。而素数的倍数一定不是素数,那么我们只要将已经判断过的素数的倍速删去即可。举个例子:2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20。

(1)判断2是否素数;是;将2的倍数删去后剩:

2,3,5,7,9,11,13,15,17,19

(2)判断3是否素数;是;将3的倍数删去后剩:

2,3,5,7,11,13,17,19

(3)判断5是否素数;是;将5的倍数删去后剩........以此类推。

那么代码该如何实现呢?假设我们要求第1个到第100个素数可以定义一个isPrime数组来标记是否为素数。再确定数组大小之前,我们要先判断一下第100个素数可能有多大。这里我们先假设为400。

for(i = 2; i <= 20; ++i)//这里i<=sqrt(400)即400的开方
    if(isPrime[i])
        for(j = 2*i; j <= 400; j+=i)    // i+i 就是 i 的倍数
            isPrime[j] = false;            //素数的倍数置零

标记完,isPrime[i]等于1的,就是素数,而且该素数就是其下标。接下来就可以获取素数了。

for(i = 2,k=1; i <= 400; ++i)
    if(map[i])     prime[k++] = i;
        //从下标1开始存放第一个素数

if(map[i]) prime[k++] = i;//从下标1开始存放第一个素数

剩下的工作就轻松多了!整体代码如下:

#include<cstdio>
#include<cstring>
#define N 1000000
#define maxn 16000000
bool map[maxn];
__int64 prime[N+5]={0};
__int64 sum[N+5]={0};
int main(void)
{
    memset(map,true,sizeof(map));
    int i,j,n,k=1;
    for(i = 2; i <= 4000; ++i)
        if(map[i])
            for(j = 2*i; j < maxn; j+=i)//将素数的倍数置零
                map[j] = false;

    for(i = 2,j = 1; i <= maxn && j <= N; ++i)
        if(map[i])
        {
            prime[k++] = i;//从下标1开始存放第一个素数
            sum[j] = sum[j-1]+prime[j]; ++j;//sum[k]为第1~k个素数的和
        }
    while(scanf("%d",&n) != EOF)
        printf("%I64d\n",sum[n]);

    return 0;
}

这个代码中,我用map数组表示状态(即isPrime数组的功能),用prime数组来存放素数。sum数组来存结果。如sum[10]的值为第1个素数到第10个素数的和。

时间: 2024-10-24 11:50:14

大素数筛子的相关文章

POJ 1811 大素数判断

数据范围很大,用米勒罗宾测试和Pollard_Rho法可以分解大数. 模板在代码中 O.O #include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> using namespace std; __int64 pri[]= {2,3,5,7,11,13,17,19,23,29,31};//用小素数表做随机种子避免第一类卡米

重复造轮子之RSA算法(一) 大素数生成

出于无聊, 打算从头实现一遍RSA算法 第一步, 大素数生成 Java的BigInteger里, 有个现成的方法 public static BigInteger probablePrime(int bitLength, Random rnd) { bitLength是期望生成的素数的二进制位数, rnd是随机数发生器 函数注释表明, 这个方法的返回值为合数的概率为2^-100 生成100个1024位的素数, 耗时13471ms 但是显然我不打算直接使用这个函数, 要做就从最底层做起! 目前的做

数论快速入门(同余、扩展欧几里德、中国剩余定理、大素数测定和整数分解、素数三种筛法、欧拉函数以及各种模板)

数学渣渣愉快的玩了一把数论,来总结一下几种常用的算法入门,不过鶸也是刚刚入门, 所以也只是粗略的记录下原理,贴下模板,以及入门题目(感受下模板怎么用的) (PS:文中蓝色字体都可以点进去查看百度原文) 附赠数论入门训练专题:点我打开专题(题目顺序基本正常,用以配套数论入门) 一.同余定理 简单粗暴的说就是:若 a-b == m 那么 a%m == b%m 这个模运算性质一眼看出...直接上入门水题: Reduced ID Numbers 附AC代码(这个也没啥模板....知道就好) #inclu

记一次使用快速幂与Miller-Rabin的大素数生成算法

大家都知道RSA的加密的安全性就是能够找到一个合适的大素数,而现在判断大素数的办法有许多,比如Fermat素性测试或者Miller-Rabin素性测试,而这里我用了Miller-Rabin素性测试的算法,具体的理论我写到下面. 算法的理论基础: Fermat定理:若n是奇素数,a是任意正整数(1≤ a≤ n?1),则 a^(n-1) ≡ 1 mod n. 2.  如果n是一个奇素数,将n?1表示成2^s*r的形式,r是奇数,a与n是互素的任何随机整数,那么a^r ≡ 1 mod n或者对某个j

csu 1552: Friends(大素数判断+二分图)

1552: Friends Time Limit: 3 Sec  Memory Limit: 256 MB Submit: 525  Solved: 136 [Submit][Status][Web Board] Description On an alien planet, every extraterrestrial is born with a number. If the sum of two numbers is a prime number, then two extraterres

第K大素数(水题)

第K大素数 Time Limit: 1000ms   Memory limit: 32768K  有疑问?点这里^_^ 题目描述 大家都知道素数是数学中很有意思的一类数,或许聪明的你已经知道了如何判定一个数是否是素数,但今天不一样了,你的任务是求第K大素数.你能快速完成吗? 输入 输入只有一个整数K. ps:我们只关心那些正整数. 输出 输出只有一行,即第K大素数. 示例输入 5 示例输出 11 提示 来源 示例程序 #include <stdio.h> #include <math.h

大素数测试和分解质因数

Prime Test http://poj.org/problem?id=1811 1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 typedef __int64 LL; 5 LL mulmod(LL a,LL b,LL c) { //ret=(a*b)%c 6 LL ret=0; 7 for(; b; a=(a<<1)%c,b>>=1) { 8 if(b&1) {

Miller_Rabbin大素数测试

伪素数: 如果存在和n互素的正整数a满足a^(n-1)≡1(mod n),则n是基于a的伪素数. 是伪素数但不是素数的个数是非常非常少的,所以如果一个数是伪素数,那么他几乎是素数. Miller_Rabbin素数测试:随机选k个a进行a^(n-1)≡1(mod n)测试,如果都满足则判断n是素数. a^(n-1)%mod用快速幂计算.对于大数相乘(两个大于int的数相乘),中间结果可能溢出,所以需要用快速幂思想进行乘法取模. Miller_Rabbin的出错率为2^(-k). 1 //Mille

2018 ACM-ICPC 中国大学生程序设计竞赛线上赛 B. Goldbach-米勒拉宾素数判定(大素数)

若干年之前的一道题,当时能写出来还是超级开心的,虽然是个板子题.一直忘记写博客,备忘一下. 米勒拉判大素数,关于米勒拉宾是个什么东西,传送门了解一下:biubiubiu~ B. Goldbach 题目传送门 自己看题意吧,直接贴代码了. 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 #i