(暫時棄坑)(半成品)ACM數論之旅18---反演定理 第二回 Mobius反演(莫比烏斯反演)((づ ̄3 ̄)づ天才第一步,雀。。。。)


 

莫比烏斯反演也是反演定理的一種

 

 

 

既然我們已經學了二項式反演定理

 

那莫比烏斯反演定理與二項式反演定理一樣,不求甚解,只求會用

 

莫比烏斯反演長下面這個樣子(=・ω・=)

 

莫比烏斯反演1

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

    (2)對任意正整數n有 

 

 莫比烏斯反演3

 

 

 

 

求μ的函數的方法很多

這里提供一種線篩的預處理(復雜度O(n)喲~~~)

 1 #include<cstdio>
 2 const int N = 1e6 + 5;
 3 int mu[N], vis[N], prime[N];
 4 int tot;//用來記錄prime的個數
 5 void init(){
 6     mu[1] = 1;
 7     for(int i = 2; i < N; i ++){
 8         if(!vis[i]){
 9             prime[tot ++] = i;
10             mu[i] = -1;
11         }
12         for(int j = 0; j < tot && i * prime[j] < N; j ++){
13             vis[i * prime[j]] = 1;
14             if(i % prime[j]) mu[i * prime[j]] = -mu[i];
15             else{
16                 mu[i * prime[j]] = 0;
17                 break;
18             }
19         }
20     }
21 }
22 int main(){
23     init();
24 }

 

 上次,有人問我μ為啥不是miu是mu

這。。。當然都可以啦,μ的英文就是mu,miu是讀音看你習慣

 

∑(っ °Д °;)っ為了證明我是對的,我特意百度了希臘字母讀音及科學方面應用

大寫
小寫
英文讀音
國際音標
意義
Α
α
alpha
/ˈ&aelig;lfə/
角度,系數,角加速度
Β
β
beta
/'beitə/
磁通系數,角度,系數
Γ
γ
gamma
/'g&aelig;mə/
電導系數,角度,比熱容比
Δ
δ
delta
/'deltə/
變化量,屈光度,一元二次方程中的判別式
Ε
ε
epsilon
/ep'silon/
對數之基數,介電常數
Ζ
ζ
zeta
/'zi:tə/
系數,方位角,阻抗,相對粘度
Η
η
eta
/'i:tə/
遲滯系數,效率
Θ
θ
theta
/'θi:tə/
溫度,角度
Ι
ι ℩
iota
/ai'oute/
微小,一點
Κ
κ
kappa
/k&aelig;pə/
介質常數,絕熱指數
λ
lambda
/'l&aelig;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代碼:

 1 #include<cstdio>
 2 #include<algorithm>
 3 using namespace std;
 4 typedef long long LL;
 5 const int N = 1e6 + 5;
 6 int mu[N], vis[N], prime[N];
 7 int tot;//用來記錄prime的個數
 8 void init(){
 9     mu[1] = 1;
10     for(int i = 2; i < N; i ++){
11         if(!vis[i]){
12             prime[tot ++] = i;
13             mu[i] = -1;
14         }
15         for(int j = 0; j < tot && i * prime[j] < N; j ++){
16             vis[i * prime[j]] = 1;
17             if(i % prime[j]) mu[i * prime[j]] = -mu[i];
18             else{
19                 mu[i * prime[j]] = 0;
20                 break;
21             }
22         }
23     }
24 }
25 LL Mobius(int a, int b){
26     LL ret = 0;
27     for(int i = 1; i <= a; i ++){//因為公式中有a/i,所以for到a就可以了 
28         ret += 1ll * mu[i] * (a / i) * (b / i);
29     }
30     //我們現在求完了總對數,但是題目要求的類似(5,7)和(7,5)算一種
31     //所以接下來我們開始去重
32     LL temp = 0;
33     for(int i = 1; i <= a; i ++){
34         temp += 1ll * mu[i] * (a / i) * (a / i);
35     } 
36     return ret - temp / 2;
37     //比如a=5,b=7那么(4,6)這樣子的區間不可能有重復的(6,4)
38     //所以重復的部分只在1~a中,所以最后減去一半的重復區間就好了 
39 }
40 int main(){
41     init();
42     int T, a, b, c, d, k;
43     scanf("%d", &T);
44     for(int cas = 1; cas <= T; cas ++){
45         scanf("%d%d%d%d%d", &a, &b, &c, &d, &k);
46         if(k == 0){
47             printf("Case %d: 0\n", cas);
48             continue;
49         }
50         b /= k; d /= k;
51         if(b > d) swap(b, d);
52         printf("Case %d: %I64d\n", cas, Mobius(b, d));
53     }
54 }
View Code

 

 

 

 

 

 

/////////////////此處施工中//////////////////

暫時棄坑。。。。

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=94200#overview

峰神掛的莫比烏斯反演章節,有興趣自己去做做,不會的去百度。。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM