【51nod】1239 欧拉函数之和

题解

写完上一道就开始写这个,大体上就是代码改了改而已= =

好吧,再推一下式子!
\(\sum_{i = 1}^{n}i = \sum_{i = 1}^{n}\sum_{d | i}\phi(d) = \sum_{i = 1}^{n}\sum_{d = 1}^{\lfloor \frac{n}{i} \rfloor} \phi(d) = \sum_{i = 1}^{n}S(\lfloor \frac{n}{i} \rfloor)\)
\(S(n) = \frac{n(n + 1)}{2} - \sum_{i = 2}^{n} S(\lfloor \frac{n}{i} \rfloor)\)
long long相乘会爆掉,前面的注意特判一下

代码

#include <bits/stdc++.h>
#define MAXN 10000005
//#define ivorysi
#define enter putchar('\n')
#define space putchar(' ')
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define eps 1e-8
#define mo 974711
#define pii pair<int,int>
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {putchar('-');x = -x;}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
const int MOD = 1000000007;
struct node {
    int64 x;
    int next,v;
}E[1000005];
int head[mo + 5],sumE;
int prime[5000005],tot,P[MAXN],phi[MAXN];
bool nonprime[MAXN];
int inc(int a,int b) {
    a = a + b;
    if(a >= MOD) a -= MOD;
    return a;
}
void add(int u,int64 x,int v) {
    E[++sumE].x = x;E[sumE].v = v;E[sumE].next = head[u];
    head[u] = sumE;
}
void Insert(int64 x,int v) {
    add(x % mo,x,v);
}
int Query(int64 x) {
    int u = x % mo;
    for(int i = head[u] ; i ; i = E[i].next) {
    if(E[i].x == x) return E[i].v;
    }
    return -1;
}
int f(int64 x) {
    if(x <= 10000000) return P[x];
    int c = Query(x); 
    if(c != -1) return c;
    int res = 0;
    for(int64 i = 2 ; i <= x ; ++i) {
    int64 r = x / (x / i);
    res = inc(1LL * (r - i + 1) * f(x / i) % MOD,res);
    i = r;
    }
    int64 a = x,b = x + 1;
    if(a & 1) b /= 2;
    else a /= 2;
    a %= MOD;b %= MOD;
    res = inc(1LL * a * b % MOD,MOD - res);
    Insert(x,res);
    return res;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    phi[1] = 1;P[1] = 1;
    for(int i = 2 ; i <= 10000000 ; ++i) {
    if(!nonprime[i]) {
        prime[++tot] = i;
        phi[i] = i - 1;
    }
    for(int j = 1 ; j <= tot ; ++j) {
        if(prime[j] > 10000000 / i) break;
        nonprime[prime[j] * i] = 1;
        if(i % prime[j] == 0) {phi[i * prime[j]] = phi[i] * prime[j];break;}
        else phi[i * prime[j]] = phi[i] * (prime[j] - 1);
    }
    P[i] = inc(P[i - 1],phi[i]);
    }
    int64 x;
    read(x);
    out(f(x));enter;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/ivorysi/p/9156881.html