链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1955
题解
为了方便叙述,我下面的
n
n
n都是原题中的
N
2
N\over 2
2N
每个卦限内情况是一样的,借助对称性可以简化问题
假设
x
>
1
,
y
>
1
,
z
>
1
x>1,y>1,z>1
x>1,y>1,z>1,那么相当于每个点都落在第一卦限中
这样的点的数目是
∑
i
=
1
n
∑
j
=
1
n
∑
k
=
1
n
[
(
i
,
j
,
k
)
=
1
]
=
∑
i
=
1
n
∑
j
=
1
n
∑
k
=
1
n
∑
d
∣
(
i
,
j
,
k
)
μ
(
d
)
=
∑
d
=
1
n
μ
(
d
)
⌊
n
d
⌋
3
\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n[(i,j,k)=1] \\=\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n\sum_{d|(i,j,k)}\mu(d)\\ =\sum_{d=1}^n\mu(d){\lfloor\frac{n}{d}\rfloor}^3
i=1∑nj=1∑nk=1∑n[(i,j,k)=1]=i=1∑nj=1∑nk=1∑nd∣(i,j,k)∑μ(d)=d=1∑nμ(d)⌊dn⌋3
这个数目直接乘以
8
8
8加到答案里即可
落在某两个坐标轴所成区域的(即xyz有一个坐标为
0
0
0),推出来是
∑
d
=
1
n
μ
(
d
)
⌊
n
d
⌋
2
\sum_{d=1}^n\mu(d){\lfloor\frac{n}{d}\rfloor}^2
d=1∑nμ(d)⌊dn⌋2
这种应该乘以
12
12
12加进答案
最后,落在坐标轴上的有
6
6
6个点
上述全部相加,然后输出即可
代码
//推式子
#include <bits/stdc++.h>
#define maxn 100010
#define ll long long
using namespace std;
ll mu[maxn], mark[maxn], prime[maxn], N;
ll read(ll x=0)
{
char c, f=1;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+c-48;
return f*x;
}
void init()
{
ll i, j;
mu[1]=1;
for(i=2;i<maxn;i++)
{
if(!mark[i])prime[++*prime]=i, mu[i]=-1;
for(j=1;j<=*prime and i*prime[j]<maxn;j++)
{
mark[i*prime[j]]=1;
if(i%prime[j]==0)break;
mu[i*prime[j]]=-mu[i];
}
}
}
void work()
{
ll i, ans=0, t;
for(i=1,N>>=1;i<=N;i++)
{
t=N/i;
ans+=mu[i]*t*t*t*8+mu[i]*t*t*12;
}
ans+=6;
printf("%lld\n",ans);
}
int main()
{
ll kase=0;
init();
while(N=read())printf("Crystal %lld: ",++kase), work();
return 0;
}