原题:https://www.luogu.org/problemnew/show/P3455
题解:莫比乌斯反演是这样的
整除分块
- 要求的值时,通过打表可以发现会有很多相同的块:
-
1 2 3 4 5 6 7 8 9 10 10 5 3 2 2 1 1 1 1 1
for(ll l=1,r;l<=min(a,b);l=r+1){ r=n/(n/l) ans+=(r-l+1)*(n/l); }
莫比乌斯反演
- 有
- 有
- μ(1)=1
- 当x=p1*p2*p3*p4*...*pn μ(x)=(-1)^n
- 其余情况为0
要求。设:f(n)
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=220000;
ll pri[N],mu[N],sum[N],a,b,d;
bool mark[N];
int cas,cnt;
void init(){
mu[1]=1;ll n=55000;//线性筛素数和mu函数
for(ll i=2;i<=n;i++){
if(!mark[i]) pri[++cnt]=i,mu[i]=-1;
for(ll j=1;j<=cnt && pri[j]*i<=n;j++){
mark[i*pri[j]]=1;
if(i%pri[j]==0) break;
mu[i*pri[j]]=-mu[i];
}
}
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i];
}
ll sol(ll a,ll b,ll d){
ll ans=0;
for(ll l=1,r;l<=min(a,b);l=r+1){
r=min(a/(a/l),b/(b/l));
ans+=(sum[r]-sum[l-1])*(a/(l*d))*(b/(l*d));
}
return ans;
}
int main(){
// freopen("test.in","r",stdin);
init();
scanf("%d",&cas);
while(cas--){
scanf("%lld%lld%lld",&a,&b,&d);
printf("%lld\n",sol(a,b,d));
}
return 0;
}