[模板]

提交至 简单的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>

using namespace std;

typedef long long ll;

const int maxn = 1000010;
const int mod = 1e9+7;

ll n;

ll val[maxn];
int f[maxn], g[maxn], h[maxn], mx_p[maxn];

int p[maxn], isnp[maxn], cnt, tot, sqr;
int in1[maxn], in2[maxn], s1[maxn], s2[maxn];

inline int (const int &x) {
if (x >= mod) return x-mod;
if (x < 0) return x+mod;
return x;
}

int getin(ll x) {
if (x >= sqr) {
if (!in1[n/x]) in1[n/x] = ++ tot;
return in1[n/x];
} else {
if (!in2[x]) in2[x] = ++ tot;
return in2[x];
}
}

ll calp(ll n) {
if (n == 1) return 0;
return mo(f[getin(n)]-g[getin(n)]+2);
}

ll calh(int n, int i) {
if (val[n] == 1) return 0;
if (val[n] < p[i-1]) return mo(calp(val[n])-s1[mx_p[val[n]]]);
else return mo(calp(val[n])-s1[i-1]);
}

int main() {
isnp[1] = 1;
for (int i = 2; i <= 1000000; i++) {
if (!isnp[i]) {p[++ cnt] = i; mx_p[i] = cnt;}
for (int j = 1; j <= cnt && p[j]*i <= 1000000; j++) {
isnp[i*p[j]] = 1;
if (i % p[j] == 0) break;
}
}
for (int i = 2; i <= 1000000; i++) if (!mx_p[i]) mx_p[i] = mx_p[i-1];
scanf("%lld", &n);
sqr = int(sqrt(n));
for (ll i = 1; i <= n; i = n/(n/i)+1) {
val[getin(n/i)] = n/i;
}
for (int i = 1; i <= tot; i++) {f[i] = (1LL*(val[i]%mod)*(val[i]%mod+1)%mod*((mod+1)/2)%mod-1)%mod; g[i] = mo(val[i]%mod-1);}
for (int i = 1; i <= cnt; i++) s1[i] = mo(s1[i-1] + (p[i] ^ 1));
for (int i = 1; i <= cnt; i++) s2[i] = mo(s2[i-1] + p[i]);
for (int i = 1; i <= cnt && 1ll*p[i]*p[i] <= n; i++) {
for (int j = 1; j <= tot && val[j] >= 1ll*p[i]*p[i]; j++) {
f[j] = mo(f[j]-1LL*p[i]*mo(f[getin(val[j]/p[i])]-s2[i-1])%mod);
g[j] = mo(g[j]-mo(g[getin(val[j]/p[i])]-(i-1)));
}
}
int mx = 0;
for (int i = 1; i <= cnt; i++) if (1ll*p[i]*p[i] <= n) mx = i;
for (int i = mx; i >= 1; i--) {
for (int j = 1; j <= tot && val[j] >= 1ll*p[i]*p[i]; j++) {
int e = 1;
ll v = p[i];
if (1ll*p[i+1]*p[i+1] > val[j]) h[j] = calh(j, i+1);
while (v <= val[j]) {
int t = 0;
if (1LL*p[i+1]*p[i+1] > val[j]/v) {
t = mo(calh(getin(val[j]/v), i+1)+1);
} else t = mo(h[getin(val[j]/v)]+1);
h[j] = mo(h[j]+1LL*(p[i]^e)*t%mod);
++ e; v *= p[i];
}
}
}
printf("%dn", mo(h[getin(n)]+1));
return 0;
}