https://www.luogu.org/fe/problem/P4450
应该不分块也可以。
求\(F(n,m,d)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}[gcd(i,j)==d]\)
模板题,直接套。
但是我的分块的上界忘记把n和m换过来了。
实验证明每次都要取min,不是一蹴而就的把n换到小的然后让r赋值n。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1e6;
int pri[MAXN+1];
int &pritop=pri[0];
int mu[MAXN+1];
void sieve(int n=MAXN) {
pritop=0;
mu[1]=1;
for(int i=2; i<=n; i++) {
if(!pri[i])
pri[++pritop]=i,mu[i]=-1;
for(int j=1; j<=pritop; j++) {
int &p=pri[j];
int t=i*p;
if(t>n)
break;
pri[t]=1;
if(i%p)
mu[t]=-mu[i];
else {
mu[t]=0;
break;
}
}
}
for(int i=1;i<=n;i++)
mu[i]+=mu[i-1];
}
ll F(int n,int m,int d){
ll res=0;
int nm=min(n,m);
for(int l=1,r;l<=nm;l=r+1){
int tn=n/l;
int tm=m/l;
r=min(n/tn,m/tm);
res+=1ll*(mu[r]-mu[l-1])*(tn/d)*(tm/d);
}
return res;
}
int main() {
#ifdef Yinku
freopen("Yinku.in","r",stdin);
#endif // Yinku
sieve();
int n,m,d;
scanf("%d%d%d\n",&n,&m,&d);
if(d==0)
puts("0\n");
else
printf("%lld\n",F(n,m,d));
return 0;
}