传送门: https://loj.ac/p/6053
题意
有 一 个 神 奇 的 函 数 f ( x ) , 满 足 以 下 性 质 : 有一个神奇的函数f(x),满足以下性质: 有一个神奇的函数f(x),满足以下性质:
- f ( 1 ) = 1 f(1)=1 f(1)=1
- f ( p c ) = p ⊕ c f(p^c)=p \oplus c f(pc)=p⊕c
- f ( a b ) = f ( a ) f ( b ) g c d ( a , b ) = 1 的 情 况 下 f(ab)=f(a)f(b)\;gcd(a,b)=1的情况下 f(ab)=f(a)f(b)gcd(a,b)=1的情况下
输 出 ∑ i = 1 n f ( i ) m o d 1 e 9 + 7 输出\sum_{i=1}^nf(i)\;mod\;1e9+7 输出∑i=1nf(i)mod1e9+7
思路
因
为
n
有
1
e
10
,
所
有
用
线
性
筛
会
T
。
因为n有1e10,所有用线性筛会T。
因为n有1e10,所有用线性筛会T。
只
能
用
亚
线
性
筛
,
而
f
明
显
是
一
个
积
性
函
数
,
可
以
洲
阁
筛
,
当
然
,
M
i
n
_
25
更
完
爆
它
。
只能用亚线性筛,而f明显是一个积性函数,可以洲阁筛,当然,Min\_25更完爆它。
只能用亚线性筛,而f明显是一个积性函数,可以洲阁筛,当然,Min_25更完爆它。
那 么 怎 么 构 造 出 一 个 M i n _ 25 筛 呢 ? 转 移 方 程 这 么 写 ? 那么怎么构造出一个Min\_25筛呢?转移方程这么写? 那么怎么构造出一个Min_25筛呢?转移方程这么写?
观 察 f ( p c ) = p ⊕ c , 对 于 一 个 质 数 p : 观察f(p^c)=p \oplus c,对于一个质数p: 观察f(pc)=p⊕c,对于一个质数p:
- i f ( p = 2 ) f ( p ) = 3 if(p=2) \;f(p)=3 if(p=2)f(p)=3
- e l s e f ( p ) = p − 1 else\;f(p)=p-1 elsef(p)=p−1
所
以
我
们
要
处
理
质
数
和
,
设
g
1
[
j
]
=
∑
i
=
2
j
1
,
g
2
[
j
]
=
∑
i
=
2
j
i
.
所以我们要处理质数和,设g1[j]=\sum_{i=2}^j1,g2[j]=\sum_{i=2}^ji.
所以我们要处理质数和,设g1[j]=∑i=2j1,g2[j]=∑i=2ji.
不
管
第
一
个
f
(
2
)
=
3
,
就
统
一
认
为
f
(
p
)
=
p
−
1
,
最
后
如
果
有
2
的
话
,
a
n
s
+
2
即
可
。
不管第一个f(2)=3,就统一认为f(p)=p-1,最后如果有2的话,ans+2即可。
不管第一个f(2)=3,就统一认为f(p)=p−1,最后如果有2的话,ans+2即可。
设 p r s [ j ] 为 前 j 个 质 数 和 , p r z [ j ] 为 前 j 个 质 数 个 数 。 设prs[j]为前j个质数和,prz[j]为前j个质数个数。 设prs[j]为前j个质数和,prz[j]为前j个质数个数。
g
函
数
状
态
转
移
:
g函数状态转移:
g函数状态转移:
g
1
(
j
,
n
)
=
g
(
j
−
1
,
n
)
−
[
g
(
j
−
1
,
n
p
j
)
−
p
r
z
[
j
−
1
]
]
g_1(j,n)=g(j-1,n)-[g(j-1,\frac{n}{p_j})-prz[j-1]]
g1(j,n)=g(j−1,n)−[g(j−1,pjn)−prz[j−1]]
g 2 ( j , n ) = g ( j − 1 , n ) − p r [ j ] ∗ ( g [ j − 1 , n p j ] − p r s [ j − 1 ] ) g_2(j,n)=g(j-1,n)-pr[j]*(g[j-1,\frac{n}{p_j}]-prs[j-1]) g2(j,n)=g(j−1,n)−pr[j]∗(g[j−1,pjn]−prs[j−1])
S
(
x
,
y
)
的
状
态
转
移
:
S(x,y)的状态转移:
S(x,y)的状态转移:
S
(
x
,
y
)
=
∑
{
g
t
[
i
d
(
x
)
]
−
s
u
m
t
[
j
−
1
]
}
+
∑
k
g
e
y
p
k
e
≤
x
F
(
p
k
e
)
∗
S
(
x
p
k
e
,
k
+
1
)
+
F
(
p
k
e
+
1
)
S(x,y)=\sum\{g_t[id(x)]-sum_t[j-1]\}+\sum_{kge y\;p_k^e\leq x}F(p_k^e)*S(\frac{x}{p_k^e},k+1)+F(p_k^{e+1})
S(x,y)=∑{gt[id(x)]−sumt[j−1]}+kgeypke≤x∑F(pke)∗S(pkex,k+1)+F(pke+1)
S ( x , y ) = ∑ { g t [ i d ( x ) ] − s u m t [ j − 1 ] } + ∑ k g e y p k e ≤ x ( p ⊕ e ) ∗ S ( x p k e , k + 1 ) + p ⊕ ( e + 1 ) S(x,y)=\sum\{g_t[id(x)]-sum_t[j-1]\}+\sum_{kge y\;p_k^e\leq x}(p \oplus e)*S(\frac{x}{p_k^e},k+1)+p \oplus (e+1) S(x,y)=∑{gt[id(x)]−sumt[j−1]}+kgeypke≤x∑(p⊕e)∗S(pkex,k+1)+p⊕(e+1)
Code
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const int N = 1e6 + 10;
ll quick_pow(ll a, ll b) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans % mod;
}
namespace Min_25 {
int is_pr[N], id1[N], id2[N], cnt;
ll n, m, T;
ll pr[N], prs[N], a[N], g1[N], g2[N];
ll inv2;
inline ll ID(ll x) {
return x <= T ? id1[x] : id2[n / x];
}
inline ll calc1(ll x) {
return (x - 1) % mod;
}
inline ll calc2(ll x) {
return x % mod * (x + 1) % mod * inv2 % mod - 1;
}
void init() {
cnt = m = 0;
inv2 = quick_pow(2, mod - 2);
T = sqrt(n + 0.5);
for(int i = 2;i <= T; i++) {
if(!is_pr[i]) pr[++cnt] = i, prs[cnt] = (prs[cnt - 1] + i) % mod;
for(int j = 1;j <= cnt && i * pr[j] <= T; j++) {
is_pr[i * pr[j]] = true;
if(i % pr[j] == 0) break;
}
}
for(ll l = 1;l <= n; l = n / (n / l) + 1) {
a[++m] = n / l;
if(a[m] <= T) id1[a[m]] = m;
else id2[n / a[m]] = m;
g1[m] = calc1(a[m]);
g2[m] = calc2(a[m]);
}
for(int i = 1;i <= cnt; i++) {
for(int j = 1;j <= m && pr[i] * pr[i] <= a[j]; j++) {
g1[j] = (g1[j] - (g1[ID(a[j] / pr[i])] - (i - 1))) % mod;
g2[j] = (g2[j] - pr[i] * (g2[ID(a[j] / pr[i])] - prs[i - 1]) % mod) % mod;
}
}
}
ll S(ll x, ll y) {
if(x <= 1 || x < pr[y]) return 0;
ll ans = (g2[ID(x)] - prs[y - 1] - (g1[ID(x)] - (y - 1)) + (y == 1 ? 2 : 0) + mod) % mod;
for(int i = y;i <= cnt && pr[i] * pr[i] <= x; i++) {
ll pe = pr[i];
for(int e = 1;pe * pr[i] <= x; e++, pe *= pr[i]) {
ans = (ans + (pr[i] ^ e) * S(x / pe, i + 1) % mod + (pr[i] ^ e + 1) % mod) % mod;
}
}
return ans % mod;
}
ll Solve(ll x) {
return n = x, init(), S(n, 1) + 1;
}
}
void solve() {
ll n; cin >> n;
ll ans = Min_25::Solve(n);
cout << (ans % mod + mod) % mod << endl;
}
signed main() {
solve();
}