版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sxh759151483/article/details/82142404
对正整数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
题目让求前n项欧拉函数的和 f(n)
首先要知道欧拉函数的一个性质
然后
然后
然后内层求和外移,可以转化为
所以
还要预处理一下前5e6项的欧拉函数和,求的时候也要分块求,从第 i 项到第 n/(n/i) 项的n/d(整除)都是相同的,所以不需要重复求,只需求出其中一个再乘上(n/(n/i) - i + 1)就可以。
然后再用map标记一下已经求过的值,避免重复计算。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int maxn = 5e6+5;
const ll inv2 = 500000004;
ll phi[maxn], prim[maxn], sum[maxn];
//9931427212
//474413482
void get_ouler() {
memset(phi, 0, sizeof phi);
phi[1] = 1;
int id = phi[0] = 0;
for(int i = 2; i < maxn; i++) {
if(!phi[i]) {
phi[i] = i - 1;
prim[id++] = i;
}
for(int j = 0; j < id && prim[j] * i < maxn; j++) {
if(i % prim[j]) {
phi[i * prim[j]] = phi[i] * (prim[j] - 1);
} else {
phi[i * prim[j]] = phi[i] * prim[j];
break;
}
}
}
for(int i = 1; i < maxn; i++){
sum[i] = (sum[i - 1] + phi[i]) % mod;
}
}
map<ll, ll>M;
ll cal(ll n){
if(n < maxn) return sum[n];
if(M[n]) return M[n];
ll l = 2, r, ans = 0;
while(l <= n){
r = n / (n / l);
ans = (ans + (r - l + 1) % mod * cal(n / l) % mod) % mod;
l = r + 1;
}
ans = (n % mod * (n % mod + 1ll) % mod * inv2 % mod - ans + mod) % mod;
if(!M[n])
M[n] = ans;
return ans % mod;
}
int main()
{
get_ouler();
ll n;
scanf("%lld", &n);
printf("%lld\n", cal(n));
return 0;
}