UVa 11014 (莫比乌斯反演) Make a Crystal

这个题是根据某个二维平面的题改编过来的。

首先把问题转化一下, 就是你站在原点(0, 0, 0)能看到多少格点。

答案分为三个部分:

  1. 八个象限里的格点,即 gcd(x, y, z) = 1,且xyz均不为0. 可以先假设xyz都是整数,然后将所求的答案乘8
  2. 12个四分之一平面中的点,可以先算(x, y, 0)(x > 0, y > 0)这样的点的个数,然后乘12
  3. 坐标轴上距原点距离为1的6个点

三维对应的莫比乌斯公式就是:

在这道题里面就是 X = Y = Z = N / 2

这道题用容斥原理或者欧拉函数也可以做,但是还是莫比乌斯反演最好写最快了。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long LL;
 6 
 7 const int maxn = 200000;
 8 int prime[maxn + 10], mu[maxn + 10];
 9 bool vis[maxn + 10];
10 
11 void Mobius()
12 {
13     mu[1] = 1;
14     int cnt = 0;
15     for(int i = 2; i <= maxn; i++)
16     {
17         if(!vis[i]) { mu[i] = -1; prime[cnt++] = i; }
18         for(int j = 0; j < cnt && (LL)i*prime[j] <= maxn; j++)
19         {
20             vis[i * prime[j]] = 1;
21             if(i % prime[j] != 0) mu[i*prime[j]] = -mu[i];
22             else { mu[i*prime[j]] = 0; break; }
23         }
24     }
25 
26     for(int i = 2; i <= maxn; i++) mu[i] += mu[i - 1];
27 }
28 
29 int main()
30 {
31     Mobius();
32 
33     int n, kase = 0;
34     while(scanf("%d", &n) == 1 && n)
35     {
36         n /= 2;
37         LL ans = 6;
38         for(int i = 1, j; i <= n; i = j + 1)
39         {
40             int t = n / i;
41             j = n / t;
42             ans += ((LL)t*t*t*8 + (LL)t*t*12) * (mu[j] - mu[i - 1]);
43         }
44         printf("Crystal %d: %lld\n", ++kase, ans);
45     }
46 
47     return 0;
48 }
代码君

 

posted @ 2015-05-06 20:28  AOQNRMGYXLMV  阅读(325)  评论(0编辑  收藏  举报