欧拉函数之和
基准时间限制:3 秒 空间限制:131072 KB 分值: 320 难度:7级算法题
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1239
对正整数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
跟莫比乌斯和函数前缀和的做法是一模一样的
#include<stdio.h>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int MAXN = 5e6 + 5;
const int MOD = 1e9 + 7;
int p[MAXN], prm[MAXN], phi[MAXN], SP[MAXN], sz;
void init() {
SP[1] = phi[1] = 1;
for(int i = 2; i < MAXN; ++i) {
if(!p[i]) {
phi[i] = i - 1;
prm[sz++] = i;
}
SP[i] = (phi[i] + SP[i - 1]) % MOD;
for(int j = 0 ; j < sz; ++j) {
int t = i * prm[j];
if(t >= MAXN) break;
p[t] = true;
if(i%prm[j]) {
phi[t] = phi[i] * (prm[j] - 1);
} else {
phi[t] = phi[i] * prm[j];
break;
}
}
}
}
unordered_map<LL, LL> mp;
inline LL PHI(LL n) {
if(n < MAXN) return SP[n];
if(mp[n]) return mp[n];
// printf("#%lld\n", n);
LL res = n %MOD * ((n + 1) % MOD) / 2, l = 2, r = 2;
while(true) {
res -= 1LL * PHI(n / r) * (r - l + 1);
res %= MOD;
if(r == n) break;
l = r + 1;
r = n / (n / l);
}
mp[n] = (res + MOD) % MOD;
return mp[n];
}
int main()
{
init();
LL n;
while(scanf("%lld", &n) != EOF) {
LL ans = PHI(n);
printf("%lld\n", ans);
}
return 0;
}