與擴充套件埃氏篩(min 25篩?)玩耍

2021-09-11 17:02:27 字數 3624 閱讀 6164

這篇部落格是一年前寫的……那時這東西好像還是個cai佬偷偷教我們的黑科技但現在似乎已經人盡皆知了……

cai佬說這東西叫做擴充套件埃氏篩,但似乎它和min25篩是乙個東西?

例題: loj6235 區間素數個數 設sum

(x

)sum(x)

sum(x)

表示小於等於x的素數個數。

假設我很蠢(這件事根本不用假設好嗎),連10以內的素數有哪些都不知道,只知道1不是素數。那麼我就會令sum

(x)=

x−

1sum(x)=x-1

sum(x)

=x−1

然後我就會做一些事情來扔掉合數,於是我從小到大處理素數。假設我在處理素數p

pp,並且想要扔掉sum

(i

)sum(i)

sum(i)

中以p為最小素因子的合數,我就會看向sum

(⌊ip

⌋)

sum(\lfloor \frac \rfloor)

sum(⌊p

i​⌋)

,由於前期扔掉了一些數,這個裡面應該只有素數和素因子大於等於p的數,排除掉小於p的素數,剩下的數乘以p應該就是我們這一輪操作要扔掉的合數,也就是說,sum

(i)−

=sum

(⌊ip

⌋)−s

um(p

−1

)sum(i)-=sum(\lfloor \frac \rfloor)-sum(p-1)

sum(i)

−=su

m(⌊p

i​⌋)

−sum

(p−1

) 設f 1(

x)=s

um(x

)f1(x)=sum(x)

f1(x)=

sum(

x),f 2(

x)=s

um(⌊

nx⌋)

f2(x)=sum(\lfloor \frac \rfloor)

f2(x)=

sum(

⌊xn​

⌋)。f1和f2都只用開根號級別的空間。

那麼我們就可以靈活運用f1和f2來完成篩法了。

複雜度(聽說)可以近似擬合為o(n

34ln⁡

n)

o(\frac}})

o(lnnn4

3​​)

#include

using

namespace std;

typedef

long

long ll;

const

int n=

1000005

;ll f1[n]

,f2[n]

,n,lim;

intmain()

printf

("%lld\n"

,f2[1]

);return0;

}

你已經學會了與素數玩耍,可以來水一道題了:loj6202 葉氏篩法

其實和上一題差不多,只是公式變成了sum

(x)−

=(su

m(⌊i

p⌋)−

sum(

p−1)

psum(x)-=(sum(\lfloor \frac \rfloor)-sum(p-1)) \times p

sum(x)

−=(s

um(⌊

pi​⌋

)−su

m(p−

1))×

p 此外,如果你不想寫高精的話,最後乙個樣例是過不去的…

#include

using

namespace std;

typedef

long

long ll;

typedef

double db;

const

int n=

1000005

;const db eps=

1e-12

;db f1[n]

,f2[n]

;ll l,r;

db sum

(ll x)

db query

(ll x)

return f2[1]

;}intmain()

例題:spoj-divcntk

…看**吧。關鍵思想是每個f(x)的貢獻是在處理x的最大質因子時算上的,x的最大質因子次數是1的時候可以用字首和快速處理,否則可以列舉處理。

#include

using

namespace std;

typedef

unsigned

long

long ull;

ull read()

const

int n=

200100

;ull n,k,lim,tot,t,ans;

ull f1[n]

,f2[n]

,pri[n]

;void

init

(ull x)

}void

work

(ull pos,ull res,ull rem)}}

intmain()

return0;

}

好吧,如果你看懂了上面那道題,那麼再來一道?loj6053 簡單的函式

這道題和上一道也差不多,就是我們要計算出質數異或1的字首和。

於是我們可以篩出質數字首和以及質數個數字首和。由於質數中偶數只有2,那麼只有2異或1後會加1,其他都會減1,這樣就能夠把質數異或1的字首和求出來了。

#include

using

namespace std;

typedef

long

long ll;

const ll mod=

1000000007

,div2=

500000004

;const

int n=

100005

;ll n,lim,tot,ans,f1[n]

,f2[n]

,s1[n]

,s2[n]

,pri[n]

;ll mul

(ll a,ll b)

ll sum

(ll x)

void

init()

for(ll i=lim/p+

1;i<=n/p/p&&i<=lim;

++i)

for(ll i=lim;i>=p*p;

--i)

}for

(ll i=

1;i<=lim;

++i)

}void

work

(ll pos,ll res,ll rem)}}

intmain()

bzoj5244

51nod 1847

uoj188

loj572

51nod 1965

51nod 1222

總結 篩法 Min 25篩

對於積性函式f x f x f x 求 i 1i n f i 其中n 1011 左右 sum f i 其中n leq 10 左右 i 1 i n f i 其 中n 1 011左 右 必須滿足的條件是 當p為質數時,f p f p f p 必須能表示為乙個多項式的形式,即f p a0 a1p a2p ...

演算法 Min 25篩

本篇文章中使用的字母 p 指 text p in text 若函式 f x 滿足,f x 是積性函式 f p 可以使用多項式表示。已知 f p 要能在常數級的時間內計算 f p x x in n min 25篩可以在 theta frac 的時間複雜度內計算 f x 的字首和 或者說 theta n...

LOJ 6202 葉氏篩法 min 25 篩

求 l,r 之間的素數之和 l 10 2 10 le r le 10 乙個有點裸的min 25篩?現在我只會篩素數的字首和 合數的過幾天再學吧 首先推薦一波yyb大佬部落格這個人很強 別那麼fake就好啦 令 f x x 顯然此處 f x 是完全積性函式 我們需要求的就是 displaystyle ...