【bzoj3560】DZY Loves Math V 歐拉函數
阿新 • • 發佈:2018-02-23
print bsp sca tdi rac for lov microsoft class
題目描述
給定n個正整數a1,a2,…,an,求
的值(答案模10^9+7)。
輸入
第一行一個正整數n。 接下來n行,每行一個正整數,分別為a1,a2,…,an。輸出
僅一行答案。樣例輸入
3
6
10
15
樣例輸出
1595
題解
歐拉函數
由於 $\varphi$ 是積性函數,所以可以單獨考慮每個質因子的貢獻。
那麽對於最終的 $a=i_1i_2\dots i_n$ ,若其包含 $p^c\ ,\ c>0$ ,則貢獻為 $\frac{p-1}{p}·p^c$ 。因此求出 $p^c$ 的總和,再乘上 $\frac{p-1}{p}$ ,再加上1(都不包含 $p$ 的情況)即可得到 $p$ 的總貢獻。
設 $a_j$ 中包含 $p^{c_j}$ ,那麽 $p^c$ 的總和就是所有與 $p$ 相關的 $\prod\limits_{j=1}^n\sum\limits_{k=0}^{c_j}p^k$ 減去不含 $p$ 的 $1$ 。
因此最終答案就是 $\prod\limits_{prime(p)}(\frac{p-1}{p}(\prod\limits_{j=1}^n\sum\limits_{k=0}^{c_{p,j}}p^k-1)+1)$ 。
線性篩預處理每個數最小的質因子,對每個數 $O(\log a)$ 分解質因數,復雜度 $O(a+n\log a)$
#include <cstdio> #define M 10000010 #define mod 1000000007 typedef long long ll; int pre[M] , prime[M] , tot , val[50] , cnt[50] , top; ll res[M]; bool np[M]; ll pow(ll x , int y) { ll ans = 1; while(y) { if(y & 1) ans = ans * x % mod; x = x * x % mod , y >>= 1; } return ans; } void init() { int n = 10000000 , i , j; for(i = 1 ; i <= n ; i ++ ) res[i] = 1; for(i = 2 ; i <= n ; i ++ ) { if(!np[i]) pre[i] = prime[++tot] = i; for(j = 1 ; j <= tot && i * prime[j] <= n ; j ++ ) { np[i * prime[j]] = 1 , pre[i * prime[j]] = prime[j]; if(i % prime[j] == 0) break; } } } int main() { init(); int n , i , x , now , sum; ll ans = 1; scanf("%d" , &n); while(n -- ) { scanf("%d" , &x); top = 0; for(i = x ; i != 1 ; i /= pre[i]) { if(pre[i] != val[top]) val[++top] = pre[i]; cnt[top] ++ ; } for(i = 1 ; i <= top ; i ++ ) { now = sum = 1; while(cnt[i]) cnt[i] -- , now *= val[i] , sum += now; res[val[i]] = res[val[i]] * sum % mod; } } for(i = 2 ; i <= 10000000 ; i ++ ) if(!np[i] && res[i] != 1) ans = ans * ((res[i] - 1 + mod) * pow(i , mod - 2) % mod * (i - 1) % mod + 1) % mod; printf("%lld\n" , ans); return 0; }
【bzoj3560】DZY Loves Math V 歐拉函數