P3455 [POI2007]ZAP-Queries (莫比乌斯反演

https://www.luogu.org/problem/P3455

题意:求满足x<=a,y<=b,gcd(x,y)=d的x,y对数。

分析:莫比乌斯反演和除法分块。

egin{split}
sum_{i=1}^{a}sum_{j=1}^{b}[gcd(i,j)=d] ewline
sum_{i=1}^{a/d}sum_{j=1}^{b/d}[gcd(i,j)=1] ewline
sum_{i=1}^{a/d}sum_{j=1}^{b/d}sum_{k|gcd(i,j)}^{ }mu(k) ewline
sum_{k=1}^{min(a/d,b/d)}mu(k)sum_{i=1}^{a/d}[k|i]sum_{j=1}^{b/d}[k|j] ewline
a'=a/d , b'=b/d ewline
sum_{k=1}^{min(a',b')}mu(k)[frac{a'}{k}][frac{b'}{k}]
end{split}

此时为n,可以再分块成$sqrt{n}$。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn = 5e4+10;
 4 int mu[maxn],prime[maxn],cnt=0;
 5 bool vis[maxn];
 6 
 7 inline void init(){
 8     mu[1] = 1;
 9     for(int i=2;i<maxn;i++){
10         if (vis[i] ==false){
11             prime[cnt++] = i;
12             mu[i] = -1;
13         }
14         for(int j=0;j<cnt&&prime[j]*i<maxn;j++){
15             vis[i*prime[j]] = true;
16             if(i%prime[j]==0) {mu[i*prime[j]] = 0;break;}
17             else mu[i*prime[j]] = -mu[i];
18         }
19     }
20     for(int i=2;i<maxn;i++)
21         mu[i] += mu[i-1];
22 }
23 
24 inline int solve(int a,int b){
25     int ans = 0;
26     if(a>b) swap(a,b);
27     for(int l=1,r;l<=a;l=r+1){
28         r = min(a/(a/l),b/(b/l));
29         ans += (mu[r]-mu[l-1])*(a/l)*(b/l);
30     }
31     return ans;
32 }
33 
34 int main(){
35     init();
36     int t,a,b,d;
37     cin>>t;
38     while(t--){
39         cin>>a>>b>>d;
40         cout<<solve(a/d,b/d)<<endl;
41     }
42     return 0;
43 }
View Code
原文地址:https://www.cnblogs.com/wzgg/p/11343476.html