【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} floor} phi(d) = sum_{i = 1}^{n}S(lfloor frac{n}{i} floor))
(S(n) = frac{n(n + 1)}{2} - sum_{i = 2}^{n} S(lfloor frac{n}{i} floor))
long long相乘会爆掉,前面的注意特判一下

代码

#include <bits/stdc++.h>
#define MAXN 10000005
//#define ivorysi
#define enter putchar('
')
#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;
}
原文地址:https://www.cnblogs.com/ivorysi/p/9156881.html