1. 程式人生 > >尤拉線性篩法求素數 學習報告

尤拉線性篩法求素數 學習報告

篩素數的方法有很多,先說一下Eratosthenes篩法,這種篩法的思想不難理解,就是對不超過n的每個正整數p,依次刪除p,2p,3p(k1)p,kp(kp<=n),最後沒被篩除的就是素數了
程式碼也是很好寫的,如下:

#include<iostream>
#include<cstdio>
#define N 100000
using namespace std;
int i,j;
bool pd[N];
int main()
{
    pd[1]=1;
    for(i=2;i<=N;i++)
      if(!pd[i])
        for
(j=i*i;j<=N;j+=i)//此處寫成i*i,一個小優化 pd[j]=1; for(i=1;i<=N;i++) if(!pd[i]) printf("%d ",i); return 0; }

這個篩法效率還是很高的,內層的迴圈次數是x=ni1<ni,這樣,迴圈的總次數小於

n2+n3+n4++nn=O(nlogn)

所以這個篩法已經足夠應付大多數題了.
但是如果n107呢,在Eratosthenes篩法裡,我們一個合數標記過很多遍,導致了時間的浪費,所以便有了一種時間複雜度近似O(n)的演算法,就是尤拉線性篩法。這種篩法出去了很多冗餘的標記和計算,先看下程式碼

#include<iostream>
#include<cstdio>
# define N 10000000
using namespace std;
int num=0,i,j,prime[1000005];
bool pd[10000005];
int main()
{
    for(i=2;i<=N;i++)
    {
      if(!pd[i])
        prime[++num]=i;//①如果是素數,選取加入prime[] 
      for(j=1;j<=num&&prime[j]*i<=N;j++)
      {
        pd[prime[j]*i]=1
; if(!i%prime[j]) //②這是為了防止出現一個合數被判斷兩次的情況發生 break; } } for(i=1;i<=num;i++) printf("%d ",prime[i]); }

根據唯一分解定理,我們可以得知任意一個合數N(N>2),都可以唯一分解成p1p2p3p4pn, 其中p1p2p3p4pn 且都是素數.
我們要確定的就是每個合數都要被篩除且只篩一遍
設合數n=p1p2p3pn(p1p2p3pn)
1.因為i是從1到N迴圈的,所以肯定先訪問n=p2p3p4pn, 又因為p1p2,所以在訪問n的時候p1n是一定執行的,由此我們可以得出所有的合數都會被標記過.
2.只要當前的i%prime[j]=0 就會退出迴圈,prime[j] 也是從小到大迴圈的,所以合數n只會在i=n=p2p3p4pn 的時候被篩掉,在i>n 時,有可能滿足條件的i=p1p2pnpk(2kn),此時prime[k]i 可以把n篩除,而根據②,在prime[1] 就break跳出迴圈了,故一個合數n都會被篩除且只篩一遍.

總結:
還是要多做一些數論題,尤其這種基礎演算法一定要知道原理及證明,否則有變式的時候就不知所措了.

相關推薦

線性素數 學習報告

篩素數的方法有很多,先說一下Eratosthenes篩法,這種篩法的思想不難理解,就是對不超過n的每個正整數p,依次刪除p,2∗p,3∗p……(k−1)∗p,k∗p(k∗p<=n),最後沒被篩除的

短小精悍的線性素數

輸入n,求n以內的所有素數演算法用兩個陣列儲存資料:一個是prime[],儲存n以內所有的素數,其index為pi,初值為0一個是is_prime[i],表示自然數i(i<=n)是不是質數。void genPrime() { memset(isPri

線性素數(C/C++版)

#include<iostream> using namespace std; const long MAXP = 200000; long prime[MAXP] = {0},num_prime = 0; int isNotPrime[MAXP] = {1, 1

快速線性素數 (模板+簡單解釋)

首先明確任何合數都能表示成一系列素數的積 第一種易於理解的方法: 注意對1的預處理即可,空間較大 var n,m,x,t :longint; i,j

POJ 3048 線性素數

一個坑: 有組資料如下: 1 1 坑很深…… //By SiriusRen #include <cstdio> #define N 200000 using namespace s

【演算法模板】素數

#include<iostream> using namespace std; const int MAXN=1000000+10; int n,cnt,prime[MAXN]; bool vis[MAXN]; void findprime(int n)

函式求法與素數

尤拉函式:     尤拉函式定義:        對於正整數n,尤拉函式Euler(n)是1到n-1中與n互質的數的個數,特別的,Euler(1) = 1,若n為質數則有 Euler(n) = n - 1      尤拉函式的兩種求法:     1.由定義和常識可以知道對

素數線性模板

bool isprime[maxm]; int primes[maxn],len; void Get_prime() { len = 0; memset ( isprime , tr

JD 題目1040:Prime Number (素數

rime 簡單 set end std tdi href num mod OJ題目:click here~~ 題目分析:輸出第k個素數 貼這麽簡單的題目,目的不清純 用篩法求素數的基本思想是:把從1開始的、某一範圍內的正整數從小到大順序排列

NEFU 2 - 猜想 - [素數]

script 教學 鏈接 ger cst 科學 mat 表示 檢測 題目鏈接:http://acm.nefu.edu.cn/JudgeOnline/problemShow.php?problem_id=2 Time Limit:3000ms  Memory Limit:6

POJ 2689 - Prime Distance - [素數]

代碼 one mini rop esc imu script less ogr 題目鏈接:http://poj.org/problem?id=2689 Time Limit: 1000MS Memory Limit: 65536K Description The branc

快速素數

這個有點難理解,我也組織不好語言,再次轉發一波。轉載出自https://blog.csdn.net/stack_queue/article/details/53560887 求素數是程式設計比賽中經常遇到的問題,最基本的方法是通過素數的定義直接判斷,只能被1和它本身整除的數就是素數了。這種方法適合

#數論# 快速分解質因數的技巧 && 素數(快速

快速分解質因數 在做題時經常遇到要分解質因數,那麼如何快速分解質因數呢? 在用篩法求素數時,我們使用線性篩的方法,並在每次篩的過程中,記錄下每個數的最小質因數。那麼在分解質因數的時候,只需要不斷除以當前數的最小質因數,就可以快速得到分解的質因數了。 給出一個簡單的例子,比如我們要求

素數POJ2262Goldbach’s Conjecture

/* 篩法求素數,首先從2開始將2的倍數全部篩掉,尋找下個未被篩掉的數字(就是下一個素數) */ #include<iostream> #include<cmath> #include<cstring> using namespace std; const int

陣列-素數

題目描述: 篩法求素數,指的是每次將一個素數的所有的倍數去掉,如果當前的數沒有被比它小的數去掉過,那麼當前的數就是素數。 比如1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 1不是素數。不用管。 2是素數,那麼2的所有的倍數要被去

【P1865】素數+區間!

#include<bits/stdc++.h> using namespace std; const int maxn=1000010; bool a[maxn]; int primesum[maxn]; void printPrimes(){ memset(a,true,size

Eratosthenes素數

Eratosthenes篩法高效求素數 篩法的思想:對於不超過n的每個非負整數p,刪除2p,3p,4p,5p,…,當處理完所有數之後,還沒有被刪除的數就是素數 這是簡易版的篩法,也最好理解 for(int i=2;i<=n;i++) for(in

ACMNO.17C語言-素數之N內的素數

題目描述 用篩法求之N內的素數。 輸入 N 輸出 0~N的素數 樣例輸入 100 樣例輸出 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 提示

數論題集1-8-Mysterious Bacteria (素數+唯一分解定理)

Dr. Mob has just discovered a Deathly Bacteria. He named it RC-01. RC-01 has a very strange reproduction system. RC-01 lives exactly x day

演算法提高 素數求和 ——素數

問題描述   輸入一個自然數n,求小於等於n的素數之和 樣例輸入 2 樣例輸出 2 資料規模和約定   測試樣例保證 2 <= n <= 2,000,000 資料量比較大,用函式判斷肯定超時,用篩法求素數可以大大提高速度,即當i為素數時,給