题意:求正方体 n*n*n,固定其中一个点在(0,0,0) 问在正方体里又多少不同的直线。这个题的难点是如果排除掉重复的直线 例如 4,4,4
那么 2,2,2 和 4, 4,4 是相同的
推荐两个博客:http://blog.csdn.net/lixuepeng_001/article/details/50577932
http://blog.csdn.net/acdreamers/article/details/8542292
可以发现,gcd(x,y,z) 必定是为1的,不然的就会重复,那么如何统计这个数目而且不重复呢,假设F(t)函数代表gcd(x,y,z)=(k 的倍数)
因为这样理解,莫比乌斯函数就是特殊的容斥,就是排除倍数的影响,因为倍数会导致一些重复,现在要求的是
根据
因为枚举的是 因子 n/gcd(a,b)==1 的因子有n个 并且就是 n的全部所以枚举的是 1~n。
再用上 加速,就是利用 在一定的区间内,因子是一样的。所以是利用下界求上界。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+7;
bool vis[maxn];
int prime[maxn],mu[maxn];
int cnt;
int sum[maxn];
void Init(){
int N=maxn;
memset(prime,0,sizeof(prime));
memset(mu,0,sizeof(mu));
memset(vis,0,sizeof(vis));
mu[1] = 1;
cnt = 0;
for(int i=2; i<N; i++){
if(!vis[i]){
prime[cnt++] = i;
mu[i] = -1;
}
for(int j=0; j<cnt&&i*prime[j]<N; j++){
vis[i*prime[j]] = 1;
if(i%prime[j]) mu[i*prime[j]] = -mu[i];
else{
mu[i*prime[j]] = 0;
break;
}
}
}
sum[0]=0;
for(int i=1;i<N;i++)
sum[i]=sum[i-1]+mu[i];
}
ll f(ll x1,ll x2)
{
ll total=0;
for(int i=1,next=0;i<=x1;i=next+1)
{
next=x1/(x1/i);
//不同倍数,但是对于n来说//个数相同,所以可以加速,求出上界
total=total+(1LL)*(sum[next]-sum[i-1])*(x1/i)*(x2/i);
//x/i 就是说有多少个这样的倍数
}
return total;
}
ll g(ll x1,ll x2,ll x3)
{
ll total=0;
for(int i=1,next=0;i<=x1;i=next+1)
{
next=x1/(x1/i);
total=total+(1LL)*(sum[next]-sum[i-1])*(x1/i)*(x2/i)*(x3/i);
}
return total;
}
int main()
{
int t;
cin>>t;
Init();
while(t--){
long long n;
scanf("%lld",&n);
long long ans=3+3*f(n,n)+g(n,n,n);
cout<<ans<<endl;
}
}