1. 程式人生 > >QQ 數——莫比烏斯函數

QQ 數——莫比烏斯函數

分享 efi 簡單的 none 枚舉 cpp 個性 span 獎勵

QQ 數(number.pas/c/cpp)
【問題描述】
企鵝國數學家 `QQ` 潛心研究數論,終於發現了一個簡單的數論問題!
一個 `QQ` 數定義為一個擁有一個大於 $ 1 $ 的完全平方數為因子的數字,一個數字的 `QQ` 值定義為這個數是 `QQ` 數的因數個數。
現在 `QQ` 想知道在 $[L,R]$ 範圍內,每個整數的 `QQ` 值之和是多少?
你只需要告訴他這個數字,他就可以給你寶貴的 $ 10 $ 分作為一個獎勵!
【輸入格式】
第一行兩個整數 $ L, R $ 代表要求的數字範圍;
【輸出格式】
輸出一個整數表示 `L~R` 裏每個數字的 $ QQ $ 值之和。

【輸入樣例】
1 10
【輸出樣例】
4
【樣例說明】
4 的 `QQ` 值為 1,8 的 `QQ` 值為 2,9 的 `QQ` 值為 1。
【數據範圍】
對於 $ 10\% $ 的數據,$ R\leq 10^4 $;
對於另外 $ 30\% $ 的數據,$ R\leq 10^6 $;
對於另外 $ 10\% $的數據,$ R \leq 10^7 $;
對於 $ 100\% $的數據,$ 1 \leq L\leq R \leq 10^9 $;
【題解】
因為 $ \mu(i) $ 含有平方因子的值為0,於是可以巧妙利用這個性質
記 $ [1,n] $ 的值為 $ \sum_{i=1}^{n} \sum_{d|i}[1-\mu(d)] =\sum_{d=1}^n[1-\mu(d)^2] \lfloor \frac{n}{d} \rfloor =\sum_{d=1}^n \lfloor \frac{n}{d} \rfloor - \sum_{d=1}^n \lfloor \frac{n}{d} \rfloor \mu(d)^2 $
然後可以發現前面的 $ \sum_{d=1}^n \lfloor \frac{n}{d} \rfloor $ 可以分塊,但後面的 $ \sum_{d=1}^n \lfloor \frac{n}{d} \rfloor \mu(d)^2 \ n \leq 10^9 $,沒有辦法預處理
考慮 $ \sum_{d=1}^n \lfloor \frac{n}{d} \rfloor \mu(d)^2 $ 的幾何意義
$ \sum_{d=1}^n \lfloor \frac{n}{d} \rfloor \mu(d)^2 = n- \lfloor \frac{n}{2} \rfloor - \lfloor \frac{n}{3} \rfloor -\lfloor \frac{n}{5} \rfloor + \lfloor \frac{n}{6} \rfloor +... $
可以發現當 $ i> \sqrt{n} $ 時 $ \lfloor \frac{n}{i} \rfloor = 0$
所以只要枚舉到 $ \sqrt{n} $ 時即可(其實還是可以分塊優化的)
然後就可以在 $ O(\sqrt{n}) $ 完成

再附一種做法:
$ -\sum_{i=2}^{\sqrt{n}}\mu(i)\sum_{j=1}^{\lfloor \frac{n}{i^2 j} \rfloor} \lfloor \frac{n}{i^2 j} \rfloor $ 直接分塊即可

技術分享圖片
 1 #include<bits/stdc++.h>
 2 #define LL long long
 3 #define _(d) while(d(isdigit(ch=getchar())))
 4 using namespace std;
 5 int R(){
 6     int x;bool f=1;char ch;_(!)if(ch==-)f=0;x=ch^48;
 7     _()x=(x<<3)+(x<<1)+(ch^48);return f?x:-x;}
 8 const int N=1e7+5;
 9 int p[N],vis[N],mu[N],l,r,tot;
10 LL make(int n){
11     LL ans=0;
12     for(int i=1;i*i<=n;i++)
13         ans+=mu[i]*(n/(i*i));
14     return ans;
15 }
16 LL work(int n){
17     LL ans=0,res=0;
18     for(int i=1,l;i<=n;i=l+1)
19         l=n/(n/i),ans+=(n/i)*(l-i+1);
20     for(int i=1,l;i<=n;i=l+1)
21         l=n/(n/i),res+=(n/i)*(make(l)-make(i-1));
22     return ans-res;
23 }
24 int main(){
25     mu[1]=1;
26     for(int i=2;i<N;i++){
27         if(!vis[i])p[++tot]=i,mu[i]=-1;
28         for(int j=1;j<=tot&&p[j]*i<N;j++){
29             vis[i*p[j]]=1;
30             if(i%p[j]==0)break;
31             mu[i*p[j]]=-mu[i];
32         }
33     }
34     l=R(),r=R();
35     printf("%lld\n",work(r)-work(l-1));
36     return 0;
37 }
View Code

2019-03-20

QQ 數——莫比烏斯函數