51nod 1239 欧拉函数之和

xiaoxiao2021-02-27  169

描述

对正整数 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

 

思路

和 51nod 1244 莫比乌斯函数之和 十分类似的一道题,因此我们可以采用同样的方法推出公式。

ni=1φ(i)

我们设 M(n)=ni=1φ(i)

已知 d|nφ(d)=n

所以有 ni=1d|iφ(d)=ni=1nid=1φ(d)=ni=1M(ni)=n×(n+1)2

因为 ni=1M(ni)=M(n)+ni=2M(ni)=n×(n+1)2

所以 M(n)=n×(n+1)2ni=2M(ni)

同样我们可以通过记忆化搜索以及分块来优化时间。

 

AC 代码

#include<cstdio> #include<cstdlib> #include<cstring> #include<stdlib.h> #include<iostream> #include<queue> #include<vector> #include<map> #include<cmath> #include<algorithm> using namespace std; typedef __int64 LL; const int maxn = 5000000; const int MOD = 1000000007; const int mod = 1e5+7; map<LL,LL> mp[mod]; LL mu[maxn]; int phi[maxn]; void init() { int j; phi[1] = 1; for(int i = 2; i < maxn; i++) if(!phi[i]) for(j = i; j < maxn; j+=i) { if(!phi[j])phi[j] = j; phi[j] = phi[j] / i * (i-1); } for(int i=1; i<maxn; i++) mu[i]=(mu[i-1]+phi[i])%MOD; } LL call(LL x) { if(x<maxn)return mu[x]; LL p=mp[x%mod][x]; if(p)return p; LL ans=(((x%MOD)*((x+1)%MOD)%MOD)*500000004)%MOD; for(LL i=2,la=0; i<=x; i=la+1) { la=x/(x/i); ans=(ans-(la-i+1)%MOD*call(x/i)%MOD+MOD)%MOD; } mp[x%mod][x]=ans; return ans; } int main() { ios::sync_with_stdio(false); init(); LL n; while(cin>>n) cout<<call(n)<<endl; return 0; }
转载请注明原文地址: https://www.6miu.com/read-16549.html

最新回复(0)