BZOJ2705 [SDOI2012]Longge的問題
阿新 • • 發佈:2017-08-16
範圍 sample nbsp 一個 aligned cnblogs 挑戰 給定 type
Description
Longge的數學成績非常好,並且他非常樂於挑戰高難度的數學問題。現在問題來了:給定一個整數N,你需要求出∑gcd(i, N)(1<=i <=N)。Input
一個整數,為N。Output
一個整數,為所求的答案。Sample Input
6Sample Output
15HINT
【數據範圍】
對於60%的數據,0<N<=2^16。
對於100%的數據,0<N<=2^32。
題解
$$\begin{aligned}
&\sum_{i=1}^N gcd(i, N)\\
&= \sum_{d|N} d\sum_{i=1}^N [gcd(i, N) = d]\\
&= \sum_{d|N} d\sum_{d|t} \mu\left(\frac td\right)\sum_{i=1}^N [t|gcd(i,N)]\\
&= \sum_{t|N} \frac Nt\sum_{d|t} d\mu\left(\frac td\right)\\
&= \sum_{t|N} \frac Nt\phi(t)
\end{aligned}$$
預處理N的質因子,枚舉其因數即可。
代碼:
#include <cstdio> typedef long long LL; const int M = 100; int n; LL ans; int pr[M], prcnt; inline void calc(int x) { int anst = x; for (int i = 0; i < prcnt; ++i) if (!(x % pr[i])) anst = anst / pr[i] * (pr[i] - 1); ans += (LL)n / x * anst; } int main() { scanf("%d", &n); int tn = n; for (int i = 2; (LL)i * i <= tn; ++i) if (!(tn % i)) { pr[prcnt++] = i; while (!(tn % i)) tn /= i; } if (tn > 1) pr[prcnt++] = tn; for (int i = 1; (LL)i * i <= n; ++i) if (!(n % i)) { calc(i); if (i != n / i) calc(n / i); } printf("%lld\n", ans); return 0; }
BZOJ2705 [SDOI2012]Longge的問題