51nod 1239 歐拉函數之和

1239 歐拉函數之和
基準時間限制:3 秒 空間限制:131072 KB 分值: 320 難度:7級算法題
對正整數n,歐拉函數是小於或等於n的數中與n互質的數的數目。此函數以其首名研究者歐拉命名,它又稱爲Euler’s totient function、φ函數、歐拉商數等。例如:φ(8) = 4(Phi(8) = 4),因爲1,3,5,7均和8互質。
S(n) = Phi(1) + Phi(2) + …… Phi(n),給出n,求S(n),例如:n = 5,S(n) = 1 + 1 + 2 + 2 + 4 = 10,定義Phi(1) = 1。由於結果很大,輸出Mod 1000000007的結果。
Input
輸入一個數N。(2 <= N <= 10^10)
Output
輸出S(n) Mod 1000000007的結果。
Input示例
5
Output示例
10

dalao:http://blog.csdn.net/alan_cty/article/details/51837101
這題和上一題很像 只是歐拉函數和莫比烏斯函數不一樣 看這個推導就行了,
至於
這裏寫圖片描述

其實手寫一下就出來了
6: 1 2 3 6
5:1 5
4:1 2 4
3:1 3
2:1 2
1:1
那麼就可以得到 1出現了6次,2出現了3次 完全就可以用 n/i了,應該是積性函數的性質

#include <bits/stdc++.h>

using namespace std;
const int mod = 1e9+7;
const int maxn = 5000010;
const int MOD = 500000004;
typedef long long ll;

ll sum_eu[maxn];
map<ll,ll> mp;
int phi[maxn];
int prime[maxn],euler[maxn],s[maxn]; 
int res;
void init()  
{  
    res=0;  
    euler[1]=1;  
    for(int i=2;i<maxn;i++)  
    {  
        if(!euler[i])  
        {  
         prime[res++]=i;  
         euler[i]=i-1;    
        }  
        for(int j=0;j<res&&i*prime[j]<maxn;j++)  
        {  
            if(i%prime[j]==0)  
            {  
                euler[prime[j]*i]=euler[i]*prime[j];  
                break;  
            }  
            euler[prime[j]*i]=euler[i]*(prime[j]-1);  
        }  

    }  
    for(int i=1;i<maxn;i++)  
    phi[i]=(euler[i]+phi[i-1])%mod;  
}  

ll solve(ll x)
{
    if(x<maxn) return phi[x];
    if(mp.count(x)) return mp[x];
    ll z=x%mod;
    ll res=0,ans=0;
    for(ll i=2,nxt=0;i<=x;i=nxt+1)
    {
        nxt=x/(x/i);
        ans+=(nxt-i+1)%mod*solve(x/i)%mod;
        ans%=mod;
    }
    res=(((z*(z+1))%mod*MOD)%mod-ans+mod)%mod;
    mp[x]=res;
    return res;
}

int main()
{
    ll n;
    init();
    // eratosthenes_sieve();
    scanf("%lld",&n);
    printf("%lld\n",solve(n) );
}
發佈了60 篇原創文章 · 獲贊 4 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章