给定下列式子:
∑
a
1
=
1
n
∑
a
2
=
1
n
.
.
.
∑
a
x
=
1
n
(
∏
j
=
1
x
a
j
k
)
f
(
gcd
(
a
1
,
a
2
.
.
.
,
a
x
)
)
⋅
gcd
(
a
1
,
a
2
.
.
.
,
a
x
)
\sum_{a_1=1}^n\sum_{a_2=1}^n...\sum_{a_x=1}^n(\prod_{j=1}^xa_j^k)f(\gcd(a_1,a_2...,a_x))⋅ \gcd(a_1,a_2...,a_x)
a1=1∑na2=1∑n...ax=1∑n(j=1∏xajk)f(gcd(a1,a2...,ax))⋅gcd(a1,a2...,ax)
其中
f
(
x
)
=
[
∃
d
>
1
:
d
2
∣
x
]
f(x)=[\exist d>1:d^2\mid x]
f(x)=[∃d>1:d2∣x],给定
t
,
k
,
x
(
1
≤
t
≤
1
0
4
,
1
≤
k
≤
1
0
9
,
1
≤
x
≤
1
0
9
)
t, k, x\ (1\le t \le 10^4,1\le k\le 10^9,1\le x\le 10^9)
t,k,x (1≤t≤104,1≤k≤109,1≤x≤109),下面
t
t
t 组查询,每次输入一个
n
(
1
≤
n
≤
2
×
1
0
5
)
n\ (1\le n\le 2\times 10^5)
n (1≤n≤2×105), 输出对应公式结果。
首先
f
(
x
)
=
∣
μ
(
x
)
∣
f(x)=|\mu(x)|
f(x)=∣μ(x)∣,令公式为
F
(
x
)
F(x)
F(x),化简如下(要实现单次询问至多
n
\sqrt{n}
n 的复杂度,所以当化简后的公式时间复杂度过高时,要想想能否通过更换枚举顺序来使得能预处理的内容更多):
令
t
=
gcd
(
a
1
,
a
2
.
.
.
,
a
x
)
t=\gcd(a_1,a_2...,a_x)
t=gcd(a1,a2...,ax),
S
(
n
)
=
∑
a
1
=
1
n
∑
a
2
=
1
n
.
.
.
∑
a
x
=
1
n
(
∏
j
=
1
x
a
j
k
)
S(n)=\sum_{a_1=1}^n\sum_{a_2=1}^n...\sum_{a_x=1}^n(\prod_{j=1}^xa_j^k)
S(n)=∑a1=1n∑a2=1n...∑ax=1n(∏j=1xajk),根据乘法分配率,
S
(
n
)
=
(
∑
i
=
1
n
i
k
)
x
S(n)=(\sum_{i=1}^ni^k)^x
S(n)=(∑i=1nik)x。我们枚举
t
t
t,因为
gcd
\gcd
gcd 为
t
t
t,所以
gcd
(
a
1
t
,
a
2
t
,
.
.
.
,
a
x
t
)
\gcd(\frac{a_1}{t},\frac{a_2}{t},...,\frac{a_x}{t})
gcd(ta1,ta2,...,tax) 一定等于1,则有
F
(
x
)
=
∑
t
=
1
n
t
x
k
∑
a
1
=
1
⌊
n
t
⌋
∑
a
2
=
1
⌊
n
t
⌋
.
.
.
∑
a
x
=
1
⌊
n
t
⌋
(
∏
j
=
1
x
a
j
k
)
f
(
t
)
⋅
t
[
gcd
(
a
1
,
a
2
,
.
.
.
,
a
x
)
=
1
]
=
∑
t
=
1
n
t
x
k
S
(
⌊
n
t
⌋
)
f
(
t
)
⋅
t
[
gcd
(
a
1
,
a
2
,
.
.
.
,
a
x
)
=
1
]
=
∑
t
=
1
n
t
x
k
S
(
⌊
n
t
⌋
)
f
(
t
)
⋅
t
∑
d
∣
t
μ
(
d
)
=
∑
t
=
1
n
t
x
k
+
1
f
(
t
)
∑
d
=
1
⌊
n
t
⌋
μ
(
d
)
d
x
k
S
(
⌊
n
t
d
⌋
)
\begin{aligned}F(x)&=\sum_{t=1}^nt^{xk}\sum_{a_1=1}^{\left\lfloor\frac{n}{t}\right\rfloor}\sum_{a_2=1}^{\left\lfloor\frac{n}{t}\right\rfloor}...\sum_{a_x=1}^{\left\lfloor\frac{n}{t}\right\rfloor}(\prod_{j=1}^xa_j^k)f(t)⋅ t[\gcd(a_1,a_2,...,a_x)=1] \\ &= \sum_{t=1}^nt^{xk}S(\left\lfloor\frac{n}{t}\right\rfloor)f(t)⋅ t[\gcd(a_1,a_2,...,a_x)=1] \\ &=\sum_{t=1}^nt^{xk}S(\left\lfloor\frac{n}{t}\right\rfloor)f(t)⋅ t\sum_{d|t}\mu(d)\\&= \sum_{t=1}^nt^{xk+1}f(t)\sum_{d=1}^{\left\lfloor\frac{n}{t}\right\rfloor}\mu(d)d^{xk}S(\left\lfloor\frac{n}{td}\right\rfloor)\end{aligned}
F(x)=t=1∑ntxka1=1∑⌊tn⌋a2=1∑⌊tn⌋...ax=1∑⌊tn⌋(j=1∏xajk)f(t)⋅t[gcd(a1,a2,...,ax)=1]=t=1∑ntxkS(⌊tn⌋)f(t)⋅t[gcd(a1,a2,...,ax)=1]=t=1∑ntxkS(⌊tn⌋)f(t)⋅td∣t∑μ(d)=t=1∑ntxk+1f(t)d=1∑⌊tn⌋μ(d)dxkS(⌊tdn⌋)
化简到这一步更换枚举对象,令
T
=
t
d
T=td
T=td,则有(这里枚举
t
t
t 或
d
d
d 都可以,若剩下除法,则计算对应的逆元)
F
(
x
)
=
∑
T
=
1
n
S
(
⌊
n
T
⌋
)
∑
t
∣
T
f
(
t
)
μ
(
T
t
)
t
x
k
+
1
(
T
t
)
x
k
=
∑
T
=
1
n
S
(
⌊
n
T
⌋
)
T
x
k
∑
t
∣
T
f
(
t
)
μ
(
T
t
)
t
=
∑
T
=
1
n
S
(
⌊
n
T
⌋
)
T
x
k
∑
t
∣
T
∣
μ
(
t
)
∣
μ
(
T
t
)
t
\begin{aligned} F(x)&=\sum_{T=1}^nS(\left\lfloor\frac{n}{T}\right\rfloor)\sum_{t|T}f(t)\mu(\frac{T}{t})t^{xk+1}(\frac{T}{t})^{xk}\\ &=\sum_{T=1}^nS(\left\lfloor\frac{n}{T}\right\rfloor)T^{xk}\sum_{t|T}f(t)\mu(\frac{T}{t})t\\&= \sum_{T=1}^nS(\left\lfloor\frac{n}{T}\right\rfloor)T^{xk}\sum_{t|T}|\mu(t)|\mu(\frac{T}{t})t\end{aligned}
F(x)=T=1∑nS(⌊Tn⌋)t∣T∑f(t)μ(tT)txk+1(tT)xk=T=1∑nS(⌊Tn⌋)Txkt∣T∑f(t)μ(tT)t=T=1∑nS(⌊Tn⌋)Txkt∣T∑∣μ(t)∣μ(tT)t
令
B
(
T
)
=
T
x
k
∑
t
∣
T
∣
μ
(
t
)
∣
μ
(
T
t
)
t
B(T)=T^{xk}\sum_{t|T}|\mu(t)|\mu(\frac{T}{t})t
B(T)=Txk∑t∣T∣μ(t)∣μ(tT)t,利用倍数枚举(调和级数复杂度)计算
μ
(
t
)
\mu(t)
μ(t) ,
μ
(
T
t
)
\mu(\frac{T}{t})
μ(tT) 和
t
t
t 对
B
(
T
)
B(T)
B(T) 的贡献即可。
则单次查询的答案即为
∑
T
=
1
n
S
(
⌊
n
T
⌋
)
B
(
T
)
\sum_{T=1}^nS(\left\lfloor\frac{n}{T}\right\rfloor)B(T)
∑T=1nS(⌊Tn⌋)B(T)。采用数论分块,单次查询时间复杂度为
n
\sqrt{n}
n (实测
405
m
s
405ms
405ms)。
然而,大佬还有更猛的做法(%%%)
对于
i
j
≤
n
<
(
i
+
1
)
j
ij\le n< (i+1)j
ij≤n<(i+1)j,
S
(
i
)
B
(
j
)
S(i)B(j)
S(i)B(j) 都会对其中的
n
n
n 产生贡献。我们考虑构造一个差分数组,在
i
j
ij
ij 的位置加,在
(
i
+
1
)
j
(i+1)j
(i+1)j 的位置减
S
(
i
)
B
(
j
)
S(i)B(j)
S(i)B(j),然后求个前缀和就得到了答案。于是我们实现了
O
(
1
)
O(1)
O(1) 查询(实测
249
m
s
249ms
249ms)。
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long LL;
const int maxn = 2e5 + 5;
const LL mod = 1e9 + 7;
int cnt;
LL global_x, global_k;
int S[maxn], B[maxn], mu[maxn], vis[maxn], prime[maxn], ans[maxn];
inline LL powmod(LL a, LL b){
LL ans = 1;
while(b){
if(b&1) ans = ans*a%mod;
a = a*a%mod;
b >>= 1;
}
return ans;
}
inline void init(){
mu[1] = 1;
for(int i = 2; i < maxn; i++){
if(!vis[i]){
prime[vis[i] = ++cnt] = i;
mu[i] = -1;
}
for(int j = 1, v; j <= vis[i] && (v = i*prime[j]) < maxn; j++){
vis[v] = j;
mu[v] = -mu[i];
if(j == vis[i]) mu[v] = 0;
}
}
for(int i = 1; i < maxn; i++)
for(int j = 1, tol = i; tol < maxn; j++, tol += i)
B[tol] = (B[tol] + i*abs(mu[i])*mu[j])%mod;
for(int i = 1; i < maxn; i++){
S[i] = (S[i - 1] + powmod(i, global_k))%mod;
B[i] = B[i]*powmod(i, global_x*global_k)%mod;
}
for(int i = 1; i < maxn; i++)
S[i] = powmod(S[i], global_x);
for(int i = 1; i < maxn; i++)
for(int j = 1, tol = i; tol < maxn; j++, tol += i){
ans[tol] = (ans[tol] + (LL)S[i]*B[j])%mod;
if(tol + j < maxn) ans[tol + j] = (ans[tol + j] - (LL)S[i]*B[j]%mod + mod)%mod;
}
for(int i = 1; i < maxn; i++) ans[i] = (ans[i] + ans[i - 1])%mod;
}
int main(){
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(false);
int t, n;
cin >> t >> global_k >> global_x;
init();
while(t--){
cin >> n;
cout << ans[n] << endl;
}
}