莫比乌斯反演裸题。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #define maxn 50050 using namespace std; int n,a,b,d,pre[maxn],miu[maxn],prime[maxn],cnt=0; bool vis[maxn]; void make_table() { miu[1]=1; for (int i=2;i<=maxn;i++) { if (vis[i]==false) { prime[++cnt]=i; miu[i]=-1; } for (int j=1;j<=cnt && i*prime[j]<=maxn;j++) { vis[i*prime[j]]=true; if (i%prime[j]!=0) miu[i*prime[j]]=-miu[i]; else { miu[i*prime[j]]=0; break; } } } for (int i=1;i<=maxn;i++) pre[i]=pre[i-1]+miu[i]; } int find(int a,int b,int d) { int i=1,ans=0; if (a>b) swap(a,b); while (i<=(a/d)) { int j; if ((a/(i*d)==0) || (b/(i*d)==0)) j=0; else j=min((a/d)/((a/d)/i),(b/d)/((b/d)/i)); ans+=(pre[j]-pre[i-1])*(a/(i*d))*(b/(i*d)); i=j+1; } return ans; } void work() { scanf("%d%d%d",&a,&b,&d); printf("%d\n",find(a,b,d)); } int main() { scanf("%d",&n); make_table(); for (int i=1;i<=n;i++) work(); return 0; }