神犇YY虐完數論後給傻×kAc出了一題
給定N, M,求1<=x<=N, 1<=y<=M且gcd(x, y)爲質數的(x, y)有多少對
kAc這種傻×必然不會了,於是向你來請教……
多組輸入
記$f(x) = \sum\limits_{i = 1}^{n}\sum\limits_{j = 1}^{m}[Gcd(i , j) = x]$
記$F(x) = \sum\limits_{x|n}f(n)$
腦補一下 , 可看出$F(x) = \lfloor{\dfrac{n}{x}}\rfloor\lfloor{\dfrac{m}{x}}\rfloor$
由於莫比烏斯反演可以得到
$f(x) = \sum\limits_{x|d}{\mu(\dfrac{d}{x})\times F(d)}$
準備工作做完了 , 開始推式子
$Ans = \sum\limits_{p\ \in\ Prime}\ \sum\limits_{i = 1}^{n}\sum\limits_{j = 1}^{m}[Gcd(i , j) = p]$
$=\sum\limits_{p\ \in\ Prime}\ \sum\limits_{p|d}{\mu(\dfrac{d}{p})\times F(d)}$
換枚舉$\dfrac{d}{p}$
$=\sum\limits_{p\ \in\ Prime}\ \sum\limits_{i = 1}^{\lfloor \frac{x}{p}\rfloor} \mu(i)\times F(i\times p)$
$=\sum\limits_{p\ \in\ Prime}\ \sum\limits_{i = 1}^{\lfloor \frac{x}{p}\rfloor} \mu(i)\times \lfloor \dfrac{n}{i \times p} \rfloor \times\lfloor \dfrac{m}{i \times p} \rfloor $
設$i \times p = k$
$=\sum\limits_{k= 1}^{n}\sum\limits_{p\ \in\ Prime , p|k}\mu(\dfrac{k}{p})\times \lfloor \dfrac{n}{k} \rfloor \times\lfloor \dfrac{m}{k} \rfloor $
$=\sum\limits_{k= 1}^{n} \lfloor \dfrac{n}{k} \rfloor \times\lfloor \dfrac{m}{k} \rfloor \times (\ \sum\limits_{p\ \in\ Prime , p|k}\mu(\dfrac{k}{p}))$
化完啦
就可以上喜聞樂見的整體分塊啦!
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define inc(i) (++ (i)) 6 #define dec(i) (-- (i)) 7 using namespace std; 8 9 const int N = 10000000 + 7; 10 int n , Mu[N] , Prime[N] , cnt , A[N]; 11 bool No_Prime[N]; 12 long long Sum[N] , Ans; 13 14 inline void Get_Mu(int n) 15 { 16 Mu[1] = 1; 17 for(int i = 2 ; i <= n ; inc(i)) 18 { 19 if(!No_Prime[i]) Prime[inc(cnt)] = i , Mu[i] = -1; 20 for(int j = 1 ; j <= cnt && i * Prime[j] <= n ; inc(j)) 21 { 22 No_Prime[i * Prime[j]] = 1; 23 if(i % Prime[j] == 0) break; 24 Mu[i * Prime[j]] = -Mu[i]; 25 } 26 } 27 for(int j = 1 ; j <= cnt ; inc(j)) 28 for(int i = 1 ; i * Prime[j] <= n ; inc(i)) 29 A[i * Prime[j]] += Mu[i]; 30 for(int i = 1 ; i <= n ; inc(i)) 31 Sum[i] = Sum[i - 1] + A[i]; 32 } 33 34 int main() 35 { 36 Get_Mu(10000000); 37 int T , n , m; scanf("%d" , &T); 38 while(T --) 39 { 40 scanf("%d%d" , &n , &m); 41 if(n > m) swap(n , m); 42 Ans = 0; 43 for(int l = 1 , r ; l <= n ; l = r + 1) 44 { 45 r = min(n / (n / l) , m / (m / l)); 46 Ans += 1ll * (n / l) * (m / l) * (Sum[r] - Sum[l - 1]); 47 } 48 printf("%lld\n" , Ans); 49 } 50 return 0; 51 }