前言:
很久以前看過了線性篩,沒怎麼注意原理,但是後來發現線性篩還有很有用的。。
比如上次做的一道題就需要找出每個數的最小質因子,先篩再找就太慢了。。一看線性篩發現就可以直接在篩的過程中處理出來了!
今天又學習了屌炸天的jzp線性篩,可以在o(n)的時間內求出尤拉函式, 莫比烏斯函式等積性函式
原理:首先jzp線性篩並不是一種新的線性篩。。其實就是jzp大牛對線性篩的一些開發應用
先回憶一下積性函式的定義 若a,b互質 則f(ab)=f(a)*f(b)的函式f 定義為積性函式,不要求a,b互質也滿足的稱為完全積性函式
尤拉函式和莫比烏斯函式都是積性函式但不是完全積性函式
假如我們要求 尤拉函式f(n)和莫比烏斯函式 mb(n)
顯然如果n的所有質因數(p1,p2...)的次數都是1,顯然p1,p2....是互質的,滿足積性函式定義,則f(n)=f(p1)*f(p2).....同理mb(n)
而如果某個質因數p的次數不為1,假設為k,我們可以看(yy)出 f(p^k)=p^k-p^(k-1)=(p-1)*p^k,同時由mobius函式定義知如果某個質因數次數大於1次,則其函式值為0
我們觀察 if(i%prime[j]==0) break; 這句**,此處要篩的數n =i*prime[j],而當i%prime[j]==0 時 顯然n%(prime[j]*prime[j])==0。
因此可以知道此時在n的質因子中 prime[j]的次數已經大於1了,就可以處理相應的尤拉函式和莫比烏斯函式了!
簡單應用:
hdu1695
題意:求[1,n]和[1,m]之間有多少個互質的數
做法:以前是用容斥做的,但是容斥需要找質因數,再二進位制列舉,比較慢
莫比烏斯函式其實就是容斥的係數,所以直接列舉可能出現的約數(其實就是1~n)用莫比烏斯函式求和即可
最後的式子(不判重)為sum(i=1 to n , mb(i)*(n/i)*(m/i));
這裡還有乙個小優化,由於是整數除法,對於i=[a,n/(n/a)] n/i都是是一樣的 ,比如 100/(21,22...25)都等於4,這樣可以提前對莫比烏斯函式求字首和,直接累加即可
具體實現見**,大神們證明了這個優化可以把複雜度降到sqrt(n)級別。具體實現起來的確是快多了,hdu直接0ms ac了!
**:
#include #includeview code#include
#include
#include
#include
using
namespace
std;
#define maxn 100000
bool notprime[maxn+10
];int prime[maxn+10
];int mb[maxn+10
];int f[maxn+10
];long
long sum[maxn+10
];int
np;long
long
n,m;
void
jzp()
for(int j=0; j)
else}}
}int
main()
while(t--)
n=min(b/k,d/k);
m=max(b/k,d/k);
long
long ans=0
;
for(int i=1;i<=n;i++)
ans=-(ans/2
);
for(int i=1;i<=n;i++)
printf(
"case %d: %i64d\n
",cas++,ans);
}return0;
}
最後貼jzp篩模板
bool notprime[maxn+10];int prime[maxn+10
];int mb[maxn+10]; //
mobius
int f[maxn+10]; //
euler
intnp;
void
jzp()
for(int j=0;j)
else}}
}
線性篩及其應用
素數的線性篩法 is prime記錄當前下標的數是不是乙個素數 第一次篩掉2的倍數 第二次篩掉3的倍數 以此。當然如果我現在要篩掉14的倍數,一定是篩2 14 3 14 5 14 7 14。篩到7就可以停了 比7大的素數比如11 11 14 11 2 7 11 2 7 在22這個數的時候會被篩到的 ...
線性篩及其擴充套件應用
好久沒寫部落格了。不過noip的努力一直沒有停止過 今天學習了線性篩的擴充套件,正好時間有空,就來寫部落格了 線性篩思路還是比較簡單,即保證每個數隻被它最小的因數篩去一次,先看裸的 includeusing namespace std const int maxn 1000010 int pri m...
線性篩法的應用
by qw 線性篩法最基礎的功能就是求 1,n 中的素數,以此為基礎,可以對他進行一些變形。變形後的線性 篩法可以實現許多其他的功能。下文中的tot均指一定區間內的質數個數 先看一道簡單的問題 求 1,n 中的m個數的最大質因子的序數 hdoj2136 這個問題可以利用線性篩法打乙個質數表,然後二分...