# Pentium.Labs

System全家桶：https://zhuanlan.zhihu.com/c_1238468913098731520

## BZOJ2005 莫比乌斯反演

“对于坐标系第一象限任意的整点(即横纵坐标均为整数的点)p(n,m)，

//证明：http://www.cnblogs.com/huhuuu/archive/2011/11/25/2263803.html

 1 #include <iostream>
2 #include <cstring>
3 #include <cmath>
4 using namespace std;
5 #define LL long long
6 #define MMX 100010
7 int mu[MMX],msum[MMX];
8 LL n,m;
9 bool check[MMX];
10 int prime[MMX];
11
12 void Moblus()
13 {
14     memset(check,false,sizeof(check));
15     mu[1] = 1;
16     int tot = 0;
17     for(int i = 2; i <= MMX; i++)
18     {
19         if( !check[i] )
20         {
21             prime[tot++] = i;
22             mu[i] = -1;
23         }
24         for(int j = 0; j < tot; j++)
25         {
26             if(i * prime[j] > MMX) break;
27             check[i * prime[j]] = true;
28             if( i % prime[j] == 0)
29             {
30                 mu[i * prime[j]] = 0;
31                 break;
32             }
33             else
34             {
35                 mu[i * prime[j]] = -mu[i];
36             }
37         }
38     }
39     msum[1]=mu[1];
40     for (int i=2;i<=MMX;i++)
41         msum[i]=msum[i-1]+mu[i];
42 }
43
44
45 LL G(int n,int m)           //加分块优化
46 {
47     LL ans = 0;
48     if(n > m)   swap(n,m);
49     for(int i = 1, la = 0; i <= n; i = la+1)
50     {
51         la = min(n/(n/i),m/(m/i));
52         ans += (LL)(msum[la] - msum[i-1])*(n/i)*(m/i);      //事先预处理：msum[n]=SUM(mu[1..n])
53     }
54     return ans;
55 }
56
57 int main()
58 {
59     Moblus();
60     cin>>n>>m;
61     LL sum=0;
62     for (LL i=1;i<=max(m,n);i++)
63         sum+=i*G(m/i,n/i);
64     sum=2*sum-n*m;
65     cout<<sum<<endl;
66 }
View Code

posted on 2014-11-16 15:37  Pentium.Labs  阅读(507)  评论(0编辑  收藏  举报

Pentium.Lab Since 1998