题意:
Visible Lattice Points POJ - 3090的三维版本
思路:
通过这个题目对莫比乌斯有了更深的认识,
比方说最原始的那个题目:100以内5的倍数,3的倍数,2的倍数,有些时候就像这个一样得倒单纯的2的倍数是很麻烦的容斥原理,但是莫比乌斯函数就是在很轻松的模拟容斥
这个题目得到gcd(x,y,z)=1是很麻烦的,但是就像莫比乌斯反演的F(n)是很容易得到的 (除法就行) , gcd( (n/a1)*k, (n/a2)*k,(n/a3)*k)一定是k的倍数,
但是得到的却是k* ( gcd( (n/a1) , (n/a2) , (n/a3) ) ) , F(1)=sigma card(k*(gcd((n/a1),(n/a2),(n/a3) ) ) );
这里就仿佛 100中有50个2的倍数,但其实里面参杂了3,5,7的倍数
通过莫比乌斯函数这种方便的容斥,很快就把单纯的 f(gcd(x,y,z)=k)给分离出来 , 这里我们的k是1
这里要注意一下gcd(0,a,b)=gcd(a,b) gcd(0,0,a)=a
#include<stdio.h>
#include<string.h>
const int MAXN=1000000;
bool check[MAXN+10];
int prime[MAXN+10];
int mu[MAXN+10];
void init()
{
memset(check,false,sizeof(check));
mu[1] = 1;
int tot = 0;
for(int i = 2; i <= MAXN; i++)
{
if( !check[i] )
{
prime[tot++] = i;
mu[i] = -1;
}
for(int j = 0; j < tot; j++)
{
if(i * prime[j] > MAXN) break;
check[i * prime[j]] = true;
if( i % prime[j] == 0)
{
mu[i * prime[j]] = 0;
break;
}
else
{
mu[i * prime[j]] = -mu[i];
}
}
}
}
int main()
{
int t,n;
init();
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
long long ans=3;
for(int i=1;i<=n;i++)
ans+=(long long)mu[i]*(n/i)*(n/i)*(n/i+3); //莫比乌斯反演 F(i)=(n/i)*(n/i)*(n/i+3) f(i)=sigma F(k*i);
printf("%lld\n",ans);
}
return 0;
}