BZOJ 1101: [POI2007]Zap(莫比乌斯反演)
解题思路
$$
\sum\limits_{i=1}n\sum\limits_{j=1}mgcd(i,j)=k
\[
\]
\sum\limits_{i=1}{\frac{n}{m}}\sum\limits_{j=1}{k}}gcd(i,j)=1
\[
\]
\sum\limits_{i=1}{\frac{n}{k}}\sum\limits_{j=1}{k}}\sum\limits_{d|n,d|m}\mu(d)
\[
\]
\sum\limits_{i=1}{n}\mu(d)\sum\limits_{i=1}{kd}}\sum\limits_{j=1}^{\frac{m}{kd}}
\[
然后这样就做完了,$\mu$搞一个前缀和,其余的整除分块
##代码
```cpp
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int MAXN = 50005;
typedef long long LL;
inline int rd(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
}
int n,miu[MAXN]={0,1},prime[MAXN],cnt,ans;
bool vis[MAXN];
int main(){
for(int i=2;i<=50000;i++){
if(!vis[i]) {prime[++cnt]=i;miu[i]=-1;}
for(int j=1;j<=cnt && prime[j]*i<=50000;j++){
vis[i*prime[j]]=1;
if(!(i%prime[j])) {miu[i*prime[j]]=0;break;}
miu[i*prime[j]]=-miu[i];
}
}
for(int i=1;i<=50000;i++) miu[i]+=miu[i-1];
n=rd();int a,b,d;
while(n--){
a=rd(),b=rd(),d=rd();if(a>b) swap(a,b);
for(int l=1,r;l<=a/d;l=r+1){
r=min((a/d)/(a/d/l),(b/d)/(b/l/d));
ans+=(miu[r]-miu[l-1])*(a/l/d)*(b/l/d);
}
printf("%d\n",ans);ans=0;
}
return 0;
}
```\]