莫比乌斯反演 - Visible Lattice Points - SPOJ - VLATTICE
题意:
给 定 一 个 n × n × n 的 立 方 体 , 从 ( 0 , 0 , 0 ) 看 过 去 , 问 能 够 看 到 多 少 个 点 。 给定一个n×n×n的立方体,从(0,0,0)看过去,问能够看到多少个点。 给定一个n×n×n的立方体,从(0,0,0)看过去,问能够看到多少个点。
空 间 中 , 一 个 点 X 能 够 被 点 Y 看 到 的 充 要 条 件 是 : 点 X 和 点 Y 的 这 条 线 段 上 , 不 存 在 其 他 点 。 空间中,一个点X能够被点Y看到的充要条件是:点X和点Y的这条线段上,不存在其他点。 空间中,一个点X能够被点Y看到的充要条件是:点X和点Y的这条线段上,不存在其他点。
Input :
The first line contains the number of test cases T. The next T lines contain an interger n
Output :
Output T lines, one corresponding to each test case.
Sample Input :
3
1
2
5
Sample Output :
7
19
175
Constraints :
T <= 50
1 <= N <= 1000000
分析:
我 们 知 道 , 在 二 维 坐 标 系 中 , 点 ( x 1 , y 1 ) 和 点 ( x 2 , y 2 ) 之 间 不 存 在 其 他 点 的 充 要 条 件 是 : 我们知道,在二维坐标系中,点(x_1,y_1)和点(x_2,y_2)之间不存在其他点的充要条件是: 我们知道,在二维坐标系中,点(x1,y1)和点(x2,y2)之间不存在其他点的充要条件是:
g c d ( x 2 − x 1 , y 2 − y 1 ) = 1 gcd(x_2-x_1,y_2-y_1)=1 gcd(x2−x1,y2−y1)=1
在 三 维 坐 标 系 中 , 点 ( x 1 , y 1 , z 1 ) 和 点 ( x 2 , y 2 , z 2 ) 之 间 不 存 在 其 他 点 的 充 要 条 件 是 : 在三维坐标系中,点(x_1,y_1,z_1)和点(x_2,y_2,z_2)之间不存在其他点的充要条件是: 在三维坐标系中,点(x1,y1,z1)和点(x2,y2,z2)之间不存在其他点的充要条件是:
g c d ( x 2 − x 1 , y 2 − y 1 , z 2 − z 1 ) = 1 gcd(x_2-x_1,y_2-y_1,z_2-z_1)=1 gcd(x2−x1,y2−y1,z2−z1)=1
由 于 我 们 从 ( 0 , 0 , 0 ) 看 , 所 以 条 件 为 : g c d ( x 2 − 0 , y 2 − 0 , z 2 − 0 ) = 1 由于我们从(0,0,0)看,所以条件为:gcd(x_2-0,y_2-0,z_2-0)=1 由于我们从(0,0,0)看,所以条件为:gcd(x2−0,y2−0,z2−0)=1
由 于 三 维 坐 标 ( i , j , k ) 都 是 可 能 为 0 的 , 因 此 我 们 先 考 虑 特 殊 情 况 : 由于三维坐标(i,j,k)都是可能为0的,因此我们先考虑特殊情况: 由于三维坐标(i,j,k)都是可能为0的,因此我们先考虑特殊情况:
① 、 当 其 中 有 两 维 坐 标 为 0 时 , 我 们 能 够 看 到 3 个 点 : ( 1 , 0 , 0 ) 、 ( 0 , 1 , 0 ) 、 ( 0 , 0 , 1 ) ①、当其中有两维坐标为0时,我们能够看到3个点:(1,0,0)、(0,1,0)、(0,0,1) ①、当其中有两维坐标为0时,我们能够看到3个点:(1,0,0)、(0,1,0)、(0,0,1)
② 、 当 其 中 有 一 维 坐 标 为 0 时 , 能 够 看 到 的 点 的 数 量 是 : 3 × ∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) = = 1 ] ②、当其中有一维坐标为0时,能够看到的点的数量是:3×\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)==1] ②、当其中有一维坐标为0时,能够看到的点的数量是:3×∑i=1n∑j=1n[gcd(i,j)==1]
③ 、 当 所 有 坐 标 都 不 为 0 时 , 能 够 看 到 的 点 点 数 量 是 : ∑ i = 1 n ∑ j = 1 n ∑ k = 1 n [ g c d ( i , j , k ) = = 1 ] ③、当所有坐标都不为0时,能够看到的点点数量是:\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n[gcd(i,j,k)==1] ③、当所有坐标都不为0时,能够看到的点点数量是:∑i=1n∑j=1n∑k=1n[gcd(i,j,k)==1]
则 答 案 为 : 则答案为: 则答案为:
A n s = 3 + 3 × ∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) = = 1 ] + ∑ i = 1 n ∑ j = 1 n ∑ k = 1 n [ g c d ( i , j , k ) = = 1 ] Ans=3+3×\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)==1]+\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n[gcd(i,j,k)==1] Ans=3+3×i=1∑nj=1∑n[gcd(i,j)==1]+i=1∑nj=1∑nk=1∑n[gcd(i,j,k)==1]
根 据 反 演 定 理 , 我 们 很 快 得 到 : 根据反演定理,我们很快得到: 根据反演定理,我们很快得到:
∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) = = 1 ] = ∑ i = 1 n μ ( i ) ⌊ n i ⌋ ⌊ n i ⌋ \sum_{i=1}^n\sum_{j=1}^n[gcd(i,j)==1]=\sum_{i=1}^n\mu(i)\lfloor\frac{n}{i}\rfloor\lfloor\frac{n}{i}\rfloor i=1∑nj=1∑n[gcd(i,j)==1]=i=1∑nμ(i)⌊in⌋⌊in⌋
同 理 : 同理: 同理:
∑ i = 1 n ∑ j = 1 n ∑ k = 1 n [ g c d ( i , j , k ) = = 1 ] = ∑ i = 1 n μ ( i ) ⌊ n i ⌋ ⌊ n i ⌋ ⌊ n i ⌋ \sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n[gcd(i,j,k)==1]=\sum_{i=1}^n\mu(i)\lfloor\frac{n}{i}\rfloor\lfloor\frac{n}{i}\rfloor\lfloor\frac{n}{i}\rfloor i=1∑nj=1∑nk=1∑n[gcd(i,j,k)==1]=i=1∑nμ(i)⌊in⌋⌊in⌋⌊in⌋
综 上 答 案 为 : 综上答案为: 综上答案为:
A n s = 3 + ∑ i = 1 n μ ( i ) ⌊ n i ⌋ ⌊ n i ⌋ ( ⌊ n i ⌋ + 3 ) Ans=3+\sum_{i=1}^n\mu(i)\lfloor\frac{n}{i}\rfloor\lfloor\frac{n}{i}\rfloor(\lfloor\frac{n}{i}\rfloor+3) Ans=3+i=1∑nμ(i)⌊in⌋⌊in⌋(⌊in⌋+3)
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const int N = 1000010;
int T, n;
int mu[N], primes[N], cnt, sum[N];
bool st[N];
ll f[N];
void get_prime(int n)
{
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!st[i])
{
primes[cnt++]=i;
mu[i]=-1;
}
for(int j=0;primes[j]*i<=n;j++)
{
st[primes[j]*i]=true;
if(i%primes[j]==0)
{
mu[i*primes[j]]=0;
break;
}
mu[i*primes[j]]=mu[i]*-1;
}
}
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+mu[i];
}
ll cal(int n)
{
ll res=0;
for(int i=1, r=1;i<=n;i=r+1)
{
r=n/(n/i);
r=min(r,n);
res+=(ll)(sum[r]-sum[i-1])*(n/i)*(n/i)*(n/i+3);
}
return res;
}
int main()
{
get_prime(N-1);
memset(f,-1,sizeof f);
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
printf("%lld\n",cal(n)+3);
}
return 0;
}