Description
求 ∑ i = 1 n ∑ j = 1 n ( i + j ) t μ 2 ( gcd ( i , j ) ) gcd ( i , j ) \sum_{i=1}^n \sum_{j=1}^n (i+j)^t \mu^2(\gcd(i,j)) \gcd(i,j) i=1∑nj=1∑n(i+j)tμ2(gcd(i,j))gcd(i,j)
q q q组询问, t t t为常量, n n n为变量。每个答案都要对 2 32 2^{32} 232取模。 n ≤ 1 0 7 , q ≤ 1 0 4 n≤10^7,q≤10^4 n≤107,q≤104。
时间限制 0.5 s − 1.5 s 0.5s-1.5s 0.5s−1.5s,空间限制256MB
Solution
Part 1: 莫反推式子
一道比较套路的推式子题,中间用到了许多推式子的trick。
∑ i = 1 n ∑ j = 1 n ( i + j ) t μ 2 ( gcd ( i , j ) ) gcd ( i , j ) \sum_{i=1}^n \sum_{j=1}^n (i+j)^t \mu^2(\gcd(i,j)) \gcd(i,j) i=1∑nj=1∑n(i+j)tμ2(gcd(i,j))gcd(i,j)
= ∑ k = 1 n μ 2 ( k ) k ∑ i = 1 n ∑ j = 1 n [ gcd ( i , j ) = k ] ( i + j ) t =\sum_{k=1}^n \mu^2(k)\ k\ \sum_{i=1}^n \sum_{j=1}^n [\gcd(i,j)=k] (i+j)^t =k=1∑nμ2(k) k i=1∑nj=1∑n[gcd(i,j)=k](i+j)t
= ∑ k = 1 n μ 2 ( k ) k t + 1 ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ [ gcd ( i , j ) = 1 ] ( i + j ) t =\sum_{k=1}^n \mu^2(k)\ k^{t+1}\ \sum_{i=1}^{\lfloor \frac n k \rfloor} \sum_{j=1}^{\lfloor \frac n k \rfloor} [\gcd(i,j)=1] (i+j)^t =k=1∑nμ2(k) kt+1 i=1∑⌊kn⌋j=1∑⌊kn⌋[gcd(i,j)=1](i+j)t
= ∑ k = 1 n μ 2 ( k ) k t + 1 ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ ( ∑ d ∣ g c d ( i , j ) μ ( d ) ) ( i + j ) t =\sum_{k=1}^n \mu^2(k)\ k^{t+1}\ \sum_{i=1}^{\lfloor \frac n k \rfloor} \sum_{j=1}^{\lfloor \frac n k \rfloor} (\sum_{d|gcd(i,j)} \mu(d))\ (i+j)^t =k=1∑nμ2(k) kt+1 i=1∑⌊kn⌋j=1∑⌊kn⌋(d∣gcd(i,j)∑μ(d)) (i+j)t
= ∑ k = 1 n μ 2 ( k ) k t + 1 ∑ d = 1 ⌊ n k ⌋ μ ( d ) d t ( ∑ i = 1 ⌊ n k d ⌋ ∑ j = 1 ⌊ n k d ⌋ ( i + j ) t ) ) =\sum_{k=1}^n \mu^2(k)\ k^{t+1}\ \sum_{d=1}^{\lfloor \frac n k \rfloor} \mu(d)\ d^{t}\ (\sum_{i=1}^{\lfloor \frac n {kd} \rfloor} \sum_{j=1}^{\lfloor \frac n {kd} \rfloor} (i+j)^t)) =k=1∑nμ2(k) kt+1 d=1∑⌊kn⌋μ(d) dt (i=1∑⌊kdn⌋j=1∑⌊kdn⌋(i+j)t))
令 F ( x ) = ∑ i = 1 x ∑ j = 1 x ( i + j ) f F(x)=\sum_{i=1}^x \sum_{j=1}^x (i+j)^f F(x)=∑i=1x∑j=1x(i+j)f,带入得
∑ k = 1 n μ 2 ( k ) k t + 1 ∑ d = 1 ⌊ n k ⌋ μ ( d ) d t F ( ⌊ n k d ⌋ ) \sum_{k=1}^n \mu^2(k)\ k^{t+1}\ \sum_{d=1}^{\lfloor \frac n k \rfloor} \mu(d)\ d^{t}\ F(\lfloor \frac n {kd} \rfloor) k=1∑nμ2(k) kt+1 d=1∑⌊kn⌋μ(d) dt F(⌊kdn⌋)
令 T = k d T=kd T=kd,转而枚举 T T T并将枚举 T T T的 ∑ \sum ∑提到最外层,
∑ T = 1 n F ( ⌊ n T ⌋ ) ∑ k ∣ T μ 2 ( k ) k t + 1 μ ( T k ) ( T k ) t \sum_{T=1}^n F(\lfloor \frac n T \rfloor)\ \sum_{k|T} \mu^2(k) k^{t+1} \mu(\frac T k) (\frac T k)^{t} T=1∑nF(⌊Tn⌋) k∣T∑μ2(k)kt+1μ(kT)(kT)t
= ∑ T = 1 n F ( ⌊ n T ⌋ ) T k ∑ k ∣ T μ 2 ( k ) k μ ( T k ) =\sum_{T=1}^n F(\lfloor \frac n T \rfloor)\ T^k\ \sum_{k|T} \mu^2(k) k\ \mu(\frac T k) =T=1∑nF(⌊Tn⌋) Tk k∣T∑μ2(k)k μ(kT)
令 G ( T ) = T k ∑ k ∣ T μ 2 ( k ) k μ ( T k ) G(T)=T^k \sum_{k|T} \mu^2(k) k\ \mu(\frac T k) G(T)=Tk∑k∣Tμ2(k)k μ(kT),带入得
∑ T = 1 n F ( ⌊ n T ⌋ ) G ( T ) \sum_{T=1}^n F(\lfloor \frac n T \rfloor)\ G(T) T=1∑nF(⌊Tn⌋) G(T)
这不是卷积形式吗 可以发现这是一个整除分块的套路式。现在我们只需要快速求出单个
F
F
F以及一个区间的
G
G
G之和即可,而后者可以通过前缀和求出。所以现在我们只需要思考如何快速求出
F
,
G
F,G
F,G函数。
Part 2: 求函数F
先考虑 F ( n ) F(n) F(n)。
∑ i = 1 n ∑ j = 1 n ( i + j ) f \sum_{i=1}^n \sum_{j=1}^n (i+j)^f i=1∑nj=1∑n(i+j)f
考虑去枚举 i + j i+j i+j。对于一个 ( i + j ) = s u m (i+j)=sum (i+j)=sum它的贡献是 s u m k p s u m sum^k\ p_{sum} sumk psum,其中 p s u m p_{sum} psum表示任选两个在 [ 1 , n ] [1,n] [1,n]区间内的整数使得它们的和恰好为 s u m sum sum的方案数。
先考虑如何求出
p
s
u
m
p_{sum}
psum。分类讨论:
①若
s
u
m
≤
n
sum≤n
sum≤n,那么
p
s
u
m
=
s
u
m
−
1
p_{sum}=sum-1
psum=sum−1;
②否则
p
s
u
m
=
2
n
−
s
u
m
+
1
p_{sum}=2n-sum+1
psum=2n−sum+1。
我们枚举 s u m sum sum(即下式中的 i i i):
∑ i = 1 n ( i − 1 ) i k + ∑ i = n + 1 2 n ( 2 n − i + 1 ) i k \sum_{i=1}^n (i-1)i^k+\sum_{i=n+1}^{2n} (2n-i+1)\ i^k i=1∑n(i−1)ik+i=n+1∑2n(2n−i+1) ik
= ( ∑ i = 1 n ∑ j = i + 1 n j k ) + ( ∑ i = n + 1 2 n ∑ j = n + 1 i j k ) =(\sum_{i=1}^n \sum_{j={i+1}}^n j^k)+(\sum_{i=n+1}^{2n} \sum_{j=n+1}^i j^k) =(i=1∑nj=i+1∑njk)+(i=n+1∑2nj=n+1∑ijk)
令 S ( x ) = ∑ i = 1 x i f S(x)=\sum_{i=1}^x i^f S(x)=∑i=1xif,带入得
( ∑ i = 1 n S ( n ) − S ( i ) ) + ∑ i = n + 1 2 n S ( i ) − S ( n ) (\sum_{i=1}^n S(n)-S(i))+\sum_{i=n+1}^{2n}\ S(i)-S(n) (i=1∑nS(n)−S(i))+i=n+1∑2n S(i)−S(n)
= n S ( n ) − ∑ i = 1 n S ( i ) + ∑ i = n + 1 2 n S ( i ) − n S ( n ) =nS(n)-\sum_{i=1}^n S(i)+\sum_{i=n+1}^{2n}\ S(i)-nS(n) =nS(n)−i=1∑nS(i)+i=n+1∑2n S(i)−nS(n)
= ∑ i = n + 1 2 n S ( i ) − ∑ i = 1 n S ( i ) =\sum_{i=n+1}^{2n} S(i)-\sum_{i=1}^n S(i) =i=n+1∑2nS(i)−i=1∑nS(i)
= ( ∑ i = 1 2 n S ( i ) − ∑ i = 1 n S ( i ) ) − ∑ i = 1 n S ( i ) =(\sum_{i=1}^{2n} S(i)-\sum_{i=1}^n S(i))-\sum_{i=1}^n S(i) =(i=1∑2nS(i)−i=1∑nS(i))−i=1∑nS(i)
令 S ′ ( x ) = ∑ i = 1 x S ( i ) S'(x)=\sum_{i=1}^x S(i) S′(x)=∑i=1xS(i),带入得
F ( n ) = S ′ ( 2 n ) − 2 S ( n ) F(n)=S'(2n)-2S(n) F(n)=S′(2n)−2S(n)
于是我们对 S S S做两遍前缀和处理即可 O ( 1 ) O(1) O(1)调用求出 F F F。
注意 S S S可以通过积性筛预处理求出来。
Part 3: 求函数G
观察一下: G ( T ) = ∑ k ∣ T μ 2 ( k ) k μ ( T k ) G(T)=\sum_{k|T} \mu^2(k) k\ \mu(\frac T k) G(T)=k∣T∑μ2(k)k μ(kT)
可以发现,这个函数是由许多积性函数( i d , μ id,\mu id,μ)组成的。所以 G G G本身也是一个积性函数,所以可以考虑线性筛积性函数。
线性筛积性函数只需要思考一种情况即可得到一般的筛法。这就是 T = p c T=p^c T=pc的情况,其中 p p p为质数且 c c c为自然数。
①
c
=
0
c=0
c=0: 此时
T
=
1
T=1
T=1,
G
(
T
)
=
1
G(T)=1
G(T)=1;
②
c
=
1
c=1
c=1: 此时
G ( T ) = μ 2 ( 1 ) × 1 × μ ( T ) + μ 2 ( T ) × T × μ ( 1 ) G(T)=\mu^2(1)×1×\mu(T)+\mu^2(T)×T×\mu(1) G(T)=μ2(1)×1×μ(T)+μ2(T)×T×μ(1)
即在这种情况中 G ( T ) = T − 1 G(T)=T-1 G(T)=T−1。
③ c = 2 c=2 c=2: 显然只有 μ 2 ( p ) × p × μ ( p ) \mu^2(p)×p×\mu(p) μ2(p)×p×μ(p)能产生非 0 0 0的贡献,而这个值等于 1 × p × ( − 1 ) = − p 1×p×(-1)=-p 1×p×(−1)=−p,所以 G ( T ) = − p G(T)=-p G(T)=−p
④当 c ≥ 3 c≥3 c≥3时,对于任意满足 u + v = c u+v=c u+v=c的正整数对 ( u , v ) (u,v) (u,v)都存在 u > 1 u>1 u>1或 v > 1 v>1 v>1,而任何质数的超过 1 1 1次方的莫比乌斯函数值都是 0 0 0,所以此时 G ( T ) = 0 G(T)=0 G(T)=0。
为什么说考虑了 T = p c T=p^c T=pc的情况之后就完全搞定了这种函数的积性筛呢?我们看一下 G G G的线性筛的代码:
//judge记录了这个数是否为合数
for (int i=2;i<=len;i++){
if (!judge[i]) G[i]=i-1,prime[++pos]=i;
//i是质数,对应的G值为i-1
for (int j=1;j<=pos;j++){
int p=prime[j];
if (i*p>len) break;//超过边界, 跳出
judge[i*p]=1;//i*p为合数
if (i%p==0){
int q=i/p;
if (q%p) G[i*p]=-p*G[i/p];
//核心语句,若不理解请先看下去
break;
}
else G[i*p]=G[i]*G[p];//积性函数递推
}
}
当 i i i被 p p p整除时,一定能分解成 i = p c × y i=p^c×y i=pc×y的形式,其中 c ≥ 1 c≥1 c≥1。即, i × p = p c ′ × y i×p=p^{c'}×y i×p=pc′×y,其中 c ′ ≥ 2 c'≥2 c′≥2。
由于 p p p为质数,所以 p c ′ p^{c'} pc′与 y y y互质,即 G ( i p ) = G ( p c ′ ) × G ( y ) G(ip)=G(p^{c'})×G(y) G(ip)=G(pc′)×G(y)。 G ( p c ′ ) G(p^{c'}) G(pc′)就是我们上面分类讨论的东西, G ( y ) G(y) G(y)是可以 O ( 1 ) O(1) O(1)调用的东西。所以这样就可以完成线性筛。
Part 4: 空间复杂度与时间复杂度的评估
本题严重卡空间,所以开的数组必须很少,只需要开下面几个数组:
①
p
r
i
m
e
prime
prime(素数)集合,由于在
[
1
,
2
×
1
0
7
]
[1,2×10^7]
[1,2×107]内的质数很少,所以这个集合可以少开一点或者直接使用
v
e
c
t
o
r
vector
vector;
②素数校验器
j
u
d
g
e
judge
judge,一定要开成bool;
③
G
G
G函数与
i
k
i^k
ik函数。
不难发现, F F F函数可以直接调用 i k i^k ik函数 O ( 1 ) O(1) O(1)求出,不需要预处理,直接放在主函数中除了大了几倍时间常数之外并无大碍。
考虑这个空间是多少,并令
m
=
2
×
1
0
7
m=2×10^7
m=2×107。
①
p
r
i
m
e
prime
prime: 开到
m
2
\frac {m} 2
2m;
②③开到
m
m
m。
由于 b o o l bool bool占用的空间只有 i n t int int的一半,所以总空间占用为 m 2 + m 2 + m + m = 3 m = 6 × 1 0 7 \frac m 2+\frac m 2+m+m=3m=6×10^7 2m+2m+m+m=3m=6×107。同时,我们不开 l o n g l o n g long\ long long long,采用unsigned int使其自然溢出实现取模即可防止 M L E MLE MLE。
时间并没有卡得很厉害,只要复杂度正确并且开了 O 2 O2 O2提交就能过。
总时间复杂度 O ( n ln ( n ) log k + n + T n ) O(\frac n {\ln(n)} \log k+n+T \sqrt n) O(ln(n)nlogk+n+Tn)。
Summary
这是一道套路题,考察了推式子的能力与一些卡空间的trick。
本题先使用了莫比乌斯反演得到了一个简化的式子,将问题拆成了两个子问题: 求出函数 F F F与 G G G。在求 F F F过程中我们巧妙枚举了 i + j i+j i+j,并将系数转化得到简明扼要的式子;在求 G G G过程中我们巧妙运用了积性函数的性质,使用分类讨论+线性筛求出了 G G G。最终,我们卡了一波空间,苦尽甘来,正解出现。
Code
//by ducati
#include<bits/stdc++.h>
#define int unsigned int
using namespace std;
const int maxl=20005;
int t,len,k,n,pos=0,ans=0;
int prime[maxl/5],pre_k[maxl],f[maxl];
bool judge[maxl];
int quick_power(int x,int y){
int res=1;
for (;y;y=y>>1,x*=x)
if (y&1) res*=x;
return res;
}
void init(){
pre_k[1]=1,f[1]=1;
for (int i=2;i<=len;i++){
if (!judge[i]) pre_k[i]=quick_power(i,k),f[i]=i-1,prime[++pos]=i;
for (int j=1;j<=pos;j++){
int p=prime[j];
if (i*p>len) break;
pre_k[i*p]=pre_k[i]*pre_k[p];
judge[i*p]=1;
if (i%p==0){
int q=i/p;
if (q%p) f[i*p]=-p*f[i/p];
break;
}
else f[i*p]=f[i]*f[p];
}
}
for (int i=1;i<=len;i++) f[i]=f[i-1]+f[i]*pre_k[i];
for (int i=1;i<=len;i++) pre_k[i]+=pre_k[i-1];
for (int i=1;i<=len;i++) pre_k[i]+=pre_k[i-1];
}
int calc(int x){return pre_k[2*x]-2*pre_k[x];}
signed main(){
cin>>t>>len>>k;len*=2;
init();
while (t--){
cin>>n;ans=0;
for (int l=1,r;l<=n;l++){
r=n/(n/l);
ans+=calc(n/l)*(f[r]-f[l-1]);
l=r;
}
cout<<ans<<endl;
}
return 0;
}
sto Fee_clе6418 orz