【bzoj3309】DZY Loves Math 莫比烏斯反演+線性篩
題目描述
對於正整數x,定義f(x)為x所含質因子的最大冪指數。例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0。
給定正整數n,m,求$\sum\limits_{i=1}^n\sum\limits_{j=1}^mf(\gcd(i,j))$
輸入
第一行一個數T,表示詢問數。
接下來T行,每行兩個數n,m,表示一個詢問。
輸出
對於每一個詢問,輸出一行一個非負整數作為回答。
樣例輸入
4
7558588 9653114
6514903 4451211
7425644 1189442
6335198 4957
樣例輸出
35793453939901
4332838845846
15400094813
題解
莫比烏斯反演+線性篩
(為了方便,以下公式默認$n\le m$)
首先有公式:
$\ \ \ \ \sum\limits_{i=1}^n\sum\limits_{j=1}^mf(\gcd(i,j))\\=\sum\limits_{d=1}^nf(d)\sum\limits_{i=1}^n\sum\limits_{j=1}^m[\gcd(i,j)=d]\\=\sum\limits_{d=1}^nf(d)\sum\limits_{i=1}^{\lfloor\frac nd\rfloor}\sum\limits_{j=1}^{\lfloor\frac md\rfloor}[\gcd(i,j)=1]\\=\sum\limits_{d=1}^nf(d)\sum\limits_{i=1}^{\lfloor\frac nd\rfloor}\sum\limits_{j=1}^{\lfloor\frac md\rfloor}\sum\limits_{p|\gcd(i,j)}\mu(p)\\=\sum\limits_{d=1}^nf(d)\sum\limits_{p=1}^{\lfloor\frac nd\rfloor}\mu(p)\lfloor\frac n{dp}\rfloor\lfloor\frac m{dp}\rfloor$
然後令$D=dp$,可以得到:
$\ \ \ \ \sum\limits_{d=1}^nf(d)\sum\limits_{p=1}^{\lfloor\frac nd\rfloor}\mu(p)\lfloor\frac n{dp}\rfloor\lfloor\frac m{dp}\rfloor\\=\sum\limits_{D=1}^n\lfloor\frac n{D}\rfloor\lfloor\frac m{D}\rfloor\sum\limits_{p|D}\mu(p)f(\frac Dp)$
這個形式看起來非常妙,然而$n$和$m$有$10^7$之大,使用枚舉倍數的調和級數時間復雜度預處理的方法的話肯定會GG(親測就算加上$\mu\neq 0$的優化也是過不去的)。
然而經過打表可以發現,對於每個$D$,$g(D)=\sum\limits_{p|D}\mu(p)f(\frac Dp)$都是$0$、$-1$或$1$中的一個值。
至此可以猜測想出結論:$g(D)$的值只與其質因子的構成有關。
事實上,具體的結論是:當$D\neq 1$時,令$D=p_1^{a_1}p_2^{a_2}...p_k^{a_k}$,則當且僅當$a_1=a_2=...=a_k$時,$g(D)=(-1)^{k+1}$;否則$g(D)=0$。
證明:
觀察$g(D)$的形式:只有當$p$中不含有平方因子時,$\mu(p)$才不為0。所以相當於:$D$的所有質因子中,每個質因子有選和不選兩種選擇,選了的話它的貢獻就會減1。
先證明$a_1$、$a_2$、...、$a_k$不全相等時,$g(D)=0$:如果所有質因子的次數不全相等,那麽考慮次數最小的那個質因子,它無論是否選擇都不會影響$f(\frac Dp)$的值,只是差在$\mu(p)$的正負。這樣選它和不選它,產生的貢獻正好正負抵消,因此$g(D)$一定是0。
再考慮$a_1=a_2=...=a_k$的情況:當且僅當每個質因子都選擇時,$f(\frac Dp)$等於$a-1$,否則等於$a$。那麽如果把$a-1$的那次貢獻看作$a$,那麽答案應該是0。所以只需要考慮把$a-1$看成$a$的變化。顯然當$k$為奇數時$\mu(p)$為負,$a-1$的貢獻為負,因此答案為$1$;否則$a-1$的貢獻為正,答案為$-1$。
所以就可以根據每個數的質因子構成來線性篩出每個數的$g$值。具體做法:如果把每個數寫成$v·p^a$的形式,那麽維護每個數的:$v$的每個質因子的次數(不全相同則為-1)、$a$的值以及質因子種類數$k$。根據這些很容易計算出當前數的$g$。註意需要考慮$v=1$的情況。
然後就可以直接求前綴和,對於每組詢問枚舉商即可。
時間復雜度$O(n+T\sqrt n)$
#include <cstdio> #include <algorithm> #define N 10000010 #define k 10000000 using namespace std; int v[N] , c[N] , cnt[N] , prime[N] , tot , sum[N]; bool np[N]; int main() { int i , j , T , n , m , last; long long ans; for(i = 2 ; i <= k ; i ++ ) { if(!np[i]) prime[++tot] = i , c[i] = cnt[i] = 1; for(j = 1 ; j <= tot && i * prime[j] <= k ; j ++ ) { np[i * prime[j]] = 1; if(i % prime[j] == 0) { v[i * prime[j]] = v[i] , c[i * prime[j]] = c[i] + 1 , cnt[i * prime[j]] = cnt[i]; break; } else { if(!v[i] || v[i] == c[i]) v[i * prime[j]] = c[i]; else v[i * prime[j]] = -1; c[i * prime[j]] = 1 , cnt[i * prime[j]] = cnt[i] + 1; } } if(v[i] && v[i] != c[i]) sum[i] = sum[i - 1]; else if(cnt[i] & 1) sum[i] = sum[i - 1] + 1; else sum[i] = sum[i - 1] - 1; } scanf("%d" , &T); while(T -- ) { scanf("%d%d" , &n , &m); ans = 0; for(i = 1 ; i <= n && i <= m ; i = last + 1) last = min(n / (n / i) , m / (m / i)) , ans += (long long)(n / i) * (m / i) * (sum[last] - sum[i - 1]); printf("%lld\n" , ans); } return 0; }
【bzoj3309】DZY Loves Math 莫比烏斯反演+線性篩