zoukankan      html  css  js  c++  java
  • 【bzoj3560】DZY Loves Math V 欧拉函数

    题目描述

    给定n个正整数a1,a2,…,an,求

    的值(答案模10^9+7)。

    输入

    第一行一个正整数n。
    接下来n行,每行一个正整数,分别为a1,a2,…,an。

    输出

    仅一行答案。

    样例输入

    3
    6
    10
    15

    样例输出

    1595


    题解

    欧拉函数

    由于 $varphi$ 是积性函数,所以可以单独考虑每个质因子的贡献。

    那么对于最终的 $a=i_1i_2dots 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$ 相关的 $prodlimits_{j=1}^nsumlimits_{k=0}^{c_j}p^k$ 减去不含 $p$ 的 $1$ 。

    因此最终答案就是 $prodlimits_{prime(p)}(frac{p-1}{p}(prodlimits_{j=1}^nsumlimits_{k=0}^{c_{p,j}}p^k-1)+1)$ 。

    线性筛预处理每个数最小的质因子,对每个数 $O(log a)$ 分解质因数,复杂度 $O(a+nlog 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
    " , ans);
        return 0;
    }
    

     

  • 相关阅读:
    android和ios系统框架
    iOS分类和扩展(Categories和Extensions)
    iOS并发编程
    认识View Controller
    JVM(Java虚拟机)
    iOS Apps核心对象
    Memory Management in Cocoa Program
    Block和GCD介绍
    iOS 系统框架分层结构
    ReLearn C(The C Programming Language.2Nd)
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/8461646.html
Copyright © 2011-2022 走看看