1. 程式人生 > >UVA - 11014 Make a Crystal (莫比烏斯反演)

UVA - 11014 Make a Crystal (莫比烏斯反演)

篩法 its const div col 由於 \n clas mes

給定一個n*n*n的立方體(中心點為原點O),選擇盡量多的點,使得對於任意兩點A,B,B不在線段OA上。

可以發現,原問題可轉化為三維坐標下的點(x,y,z)中有多少個點的gcd(x,y,z)=1。

這道題我一開始想用歐拉函數做,但我發現需要求出1-n中與每個整數x互質的數的個數,於是試圖修改一下歐拉函數的公式,結果發現計算出來的結果存在微小的偏差,原因是n不一定能被x的所有因子整除,使得(n/p)*(n/q)≠n/pq。被逼無奈,於是學了莫比烏斯反演。

莫比烏斯反演的做法是:令$n=n/2$,在$1\leqslant x,y,z\leqslant n$的限制條件下,設$f(X)$為$gcd(x,y,z)=X$的點的個數,$F(X)$為$gcd(x,y,z)=kX$的點的個數,則$F(X)=\sum\limits_{X|d}f(d)$,根據莫比烏斯反演定理則有$f(X)=\sum \limits_{X|d}\mu (\frac{d}{X})F(d)$,$f(1)$即為$x,y,z$均大於0情況下的答案。由於又有$F(X)=\left \lfloor \frac{n}{X} \right \rfloor^3$,因此可以在$O(n)$的時間內算出$f(X)$。

然後用同樣的方法可以算出$x,y,z$中有一個為0,另外兩個大於0情況下的答案,將$F(X)$換為$\left \lfloor \frac{n}{X} \right \rfloor^2$即可。

一共有8個卦限,坐標平面上的12個象限,將結果乘一乘加一加,再加上在坐標軸上的6種情況,就得到答案了。

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long ll;
 5 const ll N=1e5+10;
 6 ll n,mu[N],d[N],c[N],ka;
 7 void
init() { 8 mu[1]=1; 9 for(ll i=1; i<N; ++i)if(mu[i]) 10 for(ll j=i*2; j<N; j+=i)mu[j]-=mu[i]; 11 } 12 ll F1(ll x) {return (n/x)*(n/x)*(n/x);} 13 ll F2(ll x) {return (n/x)*(n/x);} 14 ll f(ll x,ll F(ll)) { 15 ll ret=0; 16 for(ll i=x; i<=n; i+=x)ret+=F(i)*mu[i/x];
17 return ret; 18 } 19 20 int main() { 21 init(); 22 while(scanf("%lld",&n)&&n) { 23 n/=2; 24 printf("Crystal %lld: %lld\n",++ka,f(1,F1)*8+f(1,F2)*12+6); 25 } 26 return 0; 27 }

還可以進一步優化,利用整除分塊的方法,將復雜度降到$O(\sqrt n)$

 1 #include<bits/stdc++.h>
 2 
 3 using namespace std;
 4 typedef long long ll;
 5 const ll N=1e5+10;
 6 ll n,mu[N],smu[N],ka,ans;
 7 void init() {
 8     mu[1]=1;
 9     for(ll i=1; i<N; ++i)if(mu[i])
10             for(ll j=i*2; j<N; j+=i)mu[j]-=mu[i];
11     for(ll i=1; i<N; ++i)smu[i]=smu[i-1]+mu[i];
12 }
13 
14 int main() {
15     init();
16     while(scanf("%lld",&n)&&n) {
17         n/=2;
18         ans=0;
19         for(ll l=1,r; l<=n; l=r+1) {
20             ll t=n/l;
21             r=n/t;
22             ans+=(t*t*t*8+t*t*12)*(smu[r]-smu[l-1]);
23         }
24         ans+=6;
25         printf("Crystal %lld: %lld\n",++ka,ans);
26     }
27     return 0;
28 }

以上篩莫比烏斯函數的方法復雜度是$O(nlogn)$的,也可以換成復雜度更低的$O(n)$的線性篩法,只是代碼略長,不再贅述了。

UVA - 11014 Make a Crystal (莫比烏斯反演)