素数表----欧拉筛法

欧拉筛法

欧拉筛法的数学原理:

欧拉函数:在数论,对正整数n,欧拉函数是小于n的正整数中与n互质的数的数目(φ(1)=1)。此函数以其首名研究者欧拉命名(Euler’s totient function),它又称为Euler’s totient function、φ函数、欧拉商数等。 例如φ(8)=4,因为1,3,5,7均和8互质。

欧拉筛法可以用于对给定区间内的所有素数进行打表,欧拉筛法大幅度提升了程序的效率。
时间复杂度:O(n)

代码:
#include <iostream>		//该代码用于对2-maxm(这里maxm是50)中的所有素数进行打表
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>

using namespace std;

const int maxm = 50;
int p[maxm];
bool vis[maxm];
int num = 1;

void Prime()
{
    memset(vis,true,sizeof(vis));	//初始化vis数组,用来标记是否为素数
    for(int i = 2 ; i <= maxm ; i++)
    {
        if(vis[i])			//如果i为素数,vis[i]则为true,将i存入p数组
            p[num++] = i;
        for(int j = 2 ; j < num ; j++)
        {
            if(i*p[j] > maxm)		//超出范围直接跳出
                break;
            vis[i*p[j]] = false;	//对非素数进行标记
            if(i % p[j] == 0)		//若当前素数为i的最小素因子直接跳出
                break;
        }
    }
}

void Output()
{
    for(int i = 1 ; i < num ; i++)
    {
        cout << p[i] << " ";
        if(i % 5 == 0)
            cout << "\n";
    }
}


int main()
{
    Prime();
    Output();
    return 0;
}
欧拉筛法的证明:

设合数?最小素因子为?,它的另一个大于?的素因子为?′,令?=??=?′?′。 观察上面程序片段,可以发现?循环到素因子?时,合数?第一次被标记(若循环到?之前已经跳出循环,说明? 有更小的素因子)。若也被?′标记,则是在这之前(因为?′<?),考虑?循环到?′,注意到?=??=?′?′且?和?′为不同的素因子,因此?|?′,所以当?循环到素因子?后结束,不会循环到?′,这就说明不会被?′筛去。

欧拉筛法的应用:

L – Goldbach’s Conjecture

试题来源:Ulm Local 1998
在线测试:POJ 2262,ZOJ 1951,UVA 543

In 1742, Christian Goldbach, a German amateur mathematician, sent a letter to Leonhard Euler in which he made the following conjecture:
Every even number greater than 4 can be written as the sum of two odd prime numbers.

For example:

8 = 3 + 5. Both 3 and 5 are odd prime numbers.
20 = 3 + 17 = 7 + 13.
42 = 5 + 37 = 11 + 31 = 13 + 29 = 19 + 23.

Today it is still unproven whether the conjecture is right. (Oh wait, I have the proof of course, but it is too long to write it on the margin of this page.)
Anyway, your task is now to verify Goldbach’s conjecture for all even numbers less than a million.

Input

The input will contain one or more test cases.
Each test case consists of one even integer n with 6 <= n < 1000000.
Input will be terminated by a value of 0 for n.

Output

For each test case, print one line of the form n = a + b, where a and b are odd primes. Numbers and operators should be separated by exactly one blank like in the sample output below. If there is more than one pair of odd primes adding up to n, choose the pair where the difference b – a is maximized. If there is no such pair, print a line saying “Goldbach’s conjecture is wrong.”

Sample Input
8
20
42
0

Sample Output

8 = 3 + 5
20 = 3 + 17
42 = 5 + 37

先用欧拉筛法对2-1e6之间的素数进行打表,然后便利2到n之间的元素,利用哈希散列找下标为n-i和i都是true类型的元素,直接输出即可。

AC代码:
#include <iostream>
#include <cstring>

using namespace std;

typedef long long LL;
const int maxm = 1e6;
int k = 1;
LL p[maxm];
bool vis[maxm];

void Prime()    //欧拉筛法
{
    memset(vis,true,sizeof(vis));
    for(int i = 2 ; i <= maxm ; i++)
    {
        if(vis[i])
            p[k++] = i;
        for(int j = 1 ; j < k ; j++)
        {
            if(i*p[j] > maxm)
                break;
            vis[i*p[j]] = false;
            if(i % p[j] == 0)
                break;
        }
    }
}

int main()
{
    Prime();
    LL t;
    while(cin >> t)
    {
        if(t == 0)
            break;
        for(int i = 3 ; i <= maxm ; i++)
        {
            if(vis[i] && vis[t-i])
            {
                cout << t << " = " << i << " + " << t-i << endl;
                break;  
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

柠檬ya

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值