1. 程式人生 > >[BZOJ 2749] 外星人

[BZOJ 2749] 外星人

include stdin cst begin inline tdi 定義 min 縮小

題意

  給定 $n = \prod_{k = 1} ^ m {p_k} ^ {q_k}$ .

  求最小的 x , 使得 $\phi^x(n) = 1$ .

  $1 \le p_k \le {10} ^ 5$ .

  $1 \le q_k \le {10} ^ 9$ .

分析

  設 $$R(n) = \min_{\phi^x(n) = 1} x$$ .

  我們觀察 n 是如何通過 $\phi$ 變成 1 的.

  即觀察 $\phi(n)$ 的性質.

  發現1:

    當 $n = 2$ 時, $\phi(n) = 1$ .

    當 $n > 2$ 時, $\phi(n)$ 為偶數.

  發現2:

    當 n 為偶數時, $\phi(n) \le \frac{n}{2}$ .

    因為有質因數 2 , 而在 $\phi$ 的作用下, 2 會變成 1 , 所以至少少了一個 2 .

  

  我們發現, 在 phi 的作用下, 奇數會變成偶數, 偶數每次會縮小一倍, 最後由 2 變成 1 .

  $R(n) = O(\log n)$ .

  

  我們需要更精確的結果.

  設 $f(n)$ 表示 n 通過 $\phi$ 產生 2 的能力, 設 $n = 2 ^ k \times q$ .

    $$f(n) = \left\{ \begin{aligned} & f(q) + k & , k = 0 \\ & f(\phi(n)) & , k > 0 \end{aligned} \right.$$ .

  那麽 $R(n) = f(n) + [ n 為奇數]$ .

  觀察 $f$ 的性質.

  $f(p \times q) = f(p) + f(q)$ .

  $f(p ^ k) = kf(p)$ .

  所以 $f(\sum_{k = 0} ^ m {p_k} ^ {q_k}) = \sum_{k = 0} ^ m q_kf(p_k)$ .

  求 f(1), f(2), ..., f(100000) 通過線性篩來實現.

  或者也可以直接用定義.

實現

#include <cstdio>
#include <cctype>
  
#define F(i,a,b) for (int i=(a);i<=(b);i++)
  
#define
LL long long const int N=100000; int v[N+5]; int pri[N+5],tot; LL prod[N+5]; inline int rd(void) { int x=0,f=1; char c=getchar(); for (;!isdigit(c);c=getchar()) if (c==-) f=-1; for (;isdigit(c);c=getchar()) x=x*10+c-0; return x*f; } int main(void) { #ifndef ONLINE_JUDGE freopen("sdchr.in","r",stdin); freopen("sdchr.out","w",stdout); #endif v[1]=1; prod[1]=1; F(i,2,N) { if (!v[i]) { pri[++tot]=i; prod[i]=prod[i-1]; } F(j,1,tot) { if (i*pri[j]>N) break; v[i*pri[j]]=1; prod[i*pri[j]]=prod[i]+prod[pri[j]]; if (i%pri[j]==0) break; } } int nT=rd(); F(c,1,nT) { int n=rd(); LL ans=0; int odd=1; F(i,1,n) { int p=rd(),q=rd(); ans+=1LL*prod[p]*q; if (p==2) odd=0; } ans+=odd; printf("%lld\n",ans); } return 0; }

[BZOJ 2749] 外星人