數論18——反演定理(莫比烏斯反演)
莫比烏斯反演也是反演定理的一種
既然我們已經學了二項式反演定理
那莫比烏斯反演定理與二項式反演定理一樣,不求甚解,只求會用
莫比烏斯反演長下面這個樣子(=?ω?=)
d|n,表示n能夠整除d,也就是d是n的所有因子
μ(x)是莫比烏斯函數,它是這樣計算的
μ(1) = 1
x = p1 * p2 * p3 ……*pk(x由k個不同的質數組成)則μ(x) = (-1)^k
其他情況,μ (x) = 0
比如
30 = 2 * 3 * 5
μ(30) = (-1)^3
4 = 2 * 2
μ(4) = 0
對於μ(d)函數,它有如下的常見性質:
(1)對任意正整數n有
(2)對任意正整數n有
求μ的函數的方法很多
這裏提供一種線篩的預處理(復雜度O(n)喲~~~)
#include<cstdio> const int N = 1e6 + 5; int mu[N], vis[N], prime[N]; int tot;//用來記錄prime的個數 void init(){ mu[1] = 1; for(int i = 2; i < N; i ++){ if(!vis[i]){ prime[tot ++] = i; mu[i] = -1; } for(int j = 0; j < tot && i * prime[j] < N; j ++){ vis[i * prime[j]] = 1; if(i % prime[j]) mu[i * prime[j]] = -mu[i]; else{ mu[i * prime[j]] = 0; break; } } } } int main(){ init(); }
上次,有人問我μ為啥不是miu是mu
這。。。當然都可以啦,μ的英文就是mu,miu是讀音看你習慣
∑(っ °Д °;)っ為了證明我是對的,我特意百度了希臘字母讀音及科學方面應用
大寫 | 小寫 | 英文讀音 | 國際音標 | 意義 |
Α | α | alpha | /?ælf?/ | 角度,系數,角加速度 |
Β | β | beta | /‘beit?/ | 磁通系數,角度,系數 |
Γ | γ | gamma | /‘gæm?/ | 電導系數,角度,比熱容比 |
Δ | δ | delta | /‘delt?/ | 變化量,屈光度,一元二次方程中的判別式 |
Ε | ε | epsilon | /ep‘silon/ | 對數之基數,介電常數 |
Ζ | ζ | zeta | /‘zi:t?/ | 系數,方位角,阻抗,相對粘度 |
Η | η | eta | /‘i:t?/ | 遲滯系數,效率 |
Θ | θ | theta | /‘θi:t?/ | 溫度,角度 |
Ι | ι ? | iota | /ai‘oute/ | 微小,一點 |
Κ | κ | kappa | /kæp?/ | 介質常數,絕熱指數 |
∧ | λ | lambda | /‘læmd?/ | 波長,體積,導熱系數 |
Μ | μ | mu | /mju:/ | 磁導系數,微,動摩擦系(因)數,流體動力粘度 |
Ν | ν | nu | /nju:/ | 磁阻系數,流體運動粘度,光子頻率 |
Ξ | ξ | xi | /ksi/ | 隨機數,(小)區間內的一個未知特定值 |
Ο | ο | omicron | /oumaik‘r?n/ | 高階無窮小函數 |
∏ | π | pi | /pai/ | 圓周率,π(n)表示不大於n的質數個數 |
Ρ | ρ | rho | /rou/ | 電阻系數,柱坐標和極坐標中的極徑,密度 |
∑ | σ ? | sigma | /‘sigm?/ | 總和,表面密度,跨導,正應力 |
Τ | τ | tau | /tau/ | 時間常數,切應力 |
Υ | υ | upsilon | /ju:p‘sil?n/ | 位移 |
Φ | φ | phi | /fai/ | 磁通,角,透鏡焦度,熱流量 |
Χ | χ | chi | /kai/ | 統計學中有卡方(χ^2)分布 |
Ψ | ψ | psi | /psai/ | 角速,介質電通量 |
Ω | ω | omega | /‘oumig?/ | 歐姆,角速度,交流電的電角度 |
其實莫比烏斯有兩種描述
莫比烏斯第一種描述,一般是這種
莫比烏斯第二種描述,這種也可以而且有些題這種更好
來做題吧
hdu 1695
http://acm.hdu.edu.cn/showproblem.php?pid=1695
(這題就是容斥那一章的,我就把下面的題意照搬過來了,還記得題目的就跳過題目吧)
題意:給你5個數a,b,c,d,k
在a~b中選一個x, c~d中選一個y,滿足gcd(x,y) = k , 求(x,y) 的對數
a, b, c, d, k, 0 < a <= b <= 100,000, 0 < c <= d <= 100,000, 0 <= k <= 100,000
在題目描述的最後一行有一句話,多組裏面所有的a和c都是1(這題目不是坑爹嗎(╯‵□′)╯︵┻━┻那輸入a和c有什麽用)
然後題目變成
在1~b中選一個x, 1~d中選一個y,滿足gcd(x,y) = k , 求(x,y) 的對數 。。。(無語中。。。)
前面思路一樣
先把問題就轉化為求1~a區間 和 1~b區間,gcd(x,y) = 1對數的問題
設f(d)為滿足gcd(x,y)=d的x,y的對數
我們根據莫比烏斯第二描述來做
那F(1) = f(1) + f(2) + f(3) + ....
F(2) = f(2) + f(4) + f(6) +.....
我們可以看出F(d)就是滿足gcd(x,y)為d的倍數的x,y的對數
那F(d)的公式就容易求了
F(d) = (a/d) * (b/d)
(在1~a中,有a/d個數是d的倍數,在1~b中,有b/d個數是d的倍數,這些數不管怎麽選擇,構成的gcd(x,y)都是d的倍數)
因為
F(1) = f(1) + f(2) + f(3) + ....
所以
f(1) = μ(1)*F(1) + μ(2)*F(2) + μ(3)*F(3) + ...
AC代碼:
#include<cstdio> #include<algorithm> using namespace std; typedef long long LL; const int N = 1e6 + 5; int mu[N], vis[N], prime[N]; int tot;//用來記錄prime的個數 void init(){ mu[1] = 1; for(int i = 2; i < N; i ++){ if(!vis[i]){ prime[tot ++] = i; mu[i] = -1; } for(int j = 0; j < tot && i * prime[j] < N; j ++){ vis[i * prime[j]] = 1; if(i % prime[j]) mu[i * prime[j]] = -mu[i]; else{ mu[i * prime[j]] = 0; break; } } } } LL Mobius(int a, int b){ LL ret = 0; for(int i = 1; i <= a; i ++){//因為公式中有a/i,所以for到a就可以了 ret += 1ll * mu[i] * (a / i) * (b / i); } //我們現在求完了總對數,但是題目要求的類似(5,7)和(7,5)算一種 //所以接下來我們開始去重 LL temp = 0; for(int i = 1; i <= a; i ++){ temp += 1ll * mu[i] * (a / i) * (a / i); } return ret - temp / 2; //比如a=5,b=7那麽(4,6)這樣子的區間不可能有重復的(6,4) //所以重復的部分只在1~a中,所以最後減去一半的重復區間就好了 } int main(){ init(); int T, a, b, c, d, k; scanf("%d", &T); for(int cas = 1; cas <= T; cas ++){ scanf("%d%d%d%d%d", &a, &b, &c, &d, &k); if(k == 0){ printf("Case %d: 0\n", cas); continue; } b /= k; d /= k; if(b > d) swap(b, d); printf("Case %d: %I64d\n", cas, Mobius(b, d)); } }View Code
/////////////////此處施工中//////////////////
暫時棄坑。。。。
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=94200#overview
峰神掛的莫比烏斯反演章節,有興趣自己去做做,不會的去百度。。。。
數論18——反演定理(莫比烏斯反演)