UVA11014 - Make a Crystal

链接

https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1955

题解

为了方便叙述,我下面的 n n 都是原题中的 N 2 N\over 2
每个卦限内情况是一样的,借助对称性可以简化问题
假设 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
这个数目直接乘以 8 8 加到答案里即可
落在某两个坐标轴所成区域的(即xyz有一个坐标为 0 0 ),推出来是 d = 1 n μ ( d ) n d 2 \sum_{d=1}^n\mu(d){\lfloor\frac{n}{d}\rfloor}^2
这种应该乘以 12 12 加进答案
最后,落在坐标轴上的有 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;
}

猜你喜欢

转载自blog.csdn.net/FSAHFGSADHSAKNDAS/article/details/83245323