題解-UVA12995 【Farey Sequence】
演算法:線性篩求尤拉函式,本來還想杜教篩
本文主要給剛學線性篩尤拉函式的萌新看。神仙勿噴QwQ
\(\large{\texttt{Meaning}}\)
給定一個 \(n\) ,求 \(F(n)\) :有多少組數對 \([a,b](0<a<b\le n)\) 其中 \(a,b\) 互質。
\(\large{\texttt{Solution}}\)
將 \(F(n)\) 中的數對歸類,設 \(f(n)\) 為 \(b\) 為 \(n\) 的數對 \([a,b]\) 的個數,發現 \(f\) 和 \(\varphi\) (尤拉函式,即 \(\varphi(n)=\sum_{i=1}^{n} [ \gcd (n,i) ==1]\)
然後可以用線性篩求出 \(\varphi\) ,再作一次字首和,得到 \(F\) 陣列,結束了。
還是說說怎麼線性篩求尤拉函式吧。
首先,我們有這麼一個性質:
\(\varphi(n)=n*\prod_{p|n} (p-1)/p ~~~(p\in \texttt{prime})\)
先設 \(f(n)=\prod_{p|n} (p-1)/p ~~~(p\in \texttt{prime})\)
若一個質數 \(p\) 整除 \(n\) ,則 \(f(pn)=f(n)\) ,因為 \(pn\) 和 \(n\)
則有
\[\varphi(pn)=\varphi(n)*p \]
若一個質數 \(p\) 不整除 \(n\) ,則 \(f(pn)=f(n)*(p-1)/p\) ,因為p是一個新的質因數。
則有
\[\varphi(pn)=\varphi(n)*p*(p-1)/p= \varphi(n)*(p-1) \]
發現這些式子線上性篩裡面可以使用(每個數只會被篩到一次),只需要添上幾行程式碼,且不會增加複雜度。(具體操作參考程式碼)
\(\large{\texttt{Code}}\)
#include <iostream> #include <cstdio> using namespace std; // #define PB push_back // #define MP make_pair // const int M=200010; #define int long long // #define us unsigned // #define LL long long const int N = 1000000; // const int mod = 998244353; int a, ans, prime[N + 10], phi[N + 10], top; inline void init()//線性篩尤拉函式 { phi[1] = 1;//phi[1]較特殊 for (int i = 2; i <= N; i++) { if (!phi[i]) { prime[++top] = i; phi[i] = i - 1; } for (int j = 1; j <= top && i * prime[j] <= N; j++) { if (i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j]; break; } phi[i * prime[j]] = phi[i] * phi[prime[j]]; } } for (int i = 1; i <= N; i++)//字首和 phi[i] += phi[i - 1]; } signed main() { init(); // freopen("in","r",stdin); while (~scanf("%lld", &a)) { if (!a) break; printf("%lld\n", phi[a] - phi[1]);//注意phi[1]取不了。 } return 0; }