文章目录
一个小结论
⌊ a x y ⌋ = ⌊ ⌊ a x ⌋ y ⌋ \lfloor\frac{a}{xy} \rfloor = \lfloor \frac{\lfloor \frac{a}{x} \rfloor}{y} \rfloor ⌊xya⌋=⌊y⌊xa⌋⌋
证明:
设
a = x t 1 + b 1 t 1 = y t 2 + b 2 a = x y t 2 + x b 2 + b 1 a = x y t 3 + b 3 a = xt_1+b_1\\ t_1 = yt_2 + b_2\\ a = xyt_2 + xb_2 + b_1\\ a = xyt_3+b_3 a=xt1+b1t1=yt2+b2a=xyt2+xb2+b1a=xyt3+b3
令 b 1 , b 2 b_1,b_2 b1,b2最大,即 b 1 = x − 1 , b 2 = y − 1 b_1 = x-1,b_2 = y - 1 b1=x−1,b2=y−1,则 x b 2 + b 1 = x y − 1 < x y xb_2 + b_1 = xy - 1 < xy xb2+b1=xy−1<xy,故得证。
P4450 双亲数
题意:
给出 A , B , D ( A , B , D ≤ 100000 ) A,B,D(A,B,D\leq 100000) A,B,D(A,B,D≤100000),求 ∑ a = 1 A ∑ b = 1 B ( g c d ( a , b ) = = D ) \sum_{a = 1}^{A}\sum_{b = 1}^B(gcd(a,b) == D) ∑a=1A∑b=1B(gcd(a,b)==D)
solution:
∑ i = 1 A ∑ j = 1 B [ g c d ( i , j ) = = D ] = ∑ i = 1 ⌊ A D ⌋ ∑ j = 1 ⌊ B D ⌋ [ g c d ( i , j ) = = 1 ] = ∑ i = 1 ⌊ A D ⌋ ∑ j = 1 ⌊ B D ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) = ∑ d = 1 m i n ( ⌊ A D ⌋ , ⌊ B D ⌋ ) ∑ i = 1 ⌊ A D ⌋ ∑ j = 1 ⌊ B D ⌋ [ d ∣ i , d ∣ j ] μ ( d ) = ∑ d = 1 m i n ( ⌊ A D ⌋ , ⌊ B D ⌋ ) ⌊ A D d ⌋ ⌊ B D d ⌋ μ ( d ) \begin{alignat}{2} &\sum_{i = 1}^{A}\sum_{j = 1}^B[gcd(i,j) == D]\\ =& \sum_{i = 1}^{\lfloor \frac{A}{D} \rfloor}\sum_{j = 1}^{\lfloor \frac{B}{D} \rfloor}[gcd(i,j) == 1] \\ =& \sum_{i = 1}^{\lfloor \frac{A}{D} \rfloor}\sum_{j = 1}^{\lfloor \frac{B}{D} \rfloor}\sum_{d|gcd(i,j)} \mu(d) \\ =& \sum_{d = 1}^{min(\lfloor \frac{A}{D} \rfloor,\lfloor \frac{B}{D} \rfloor)}\sum_{i = 1}^{\lfloor \frac{A}{D} \rfloor}\sum_{j = 1}^{\lfloor \frac{B}{D} \rfloor}[d|i,d|j] \mu(d)\\ =&\sum_{d = 1}^{min(\lfloor \frac{A}{D} \rfloor,\lfloor \frac{B}{D} \rfloor)}\lfloor \frac{A}{Dd} \rfloor \lfloor \frac{B}{Dd}\rfloor\mu(d) \end{alignat} ====i=1∑Aj=1∑B[gcd(i,j)==D]i=1∑⌊DA⌋j=1∑⌊DB⌋[gcd(i,j)==1]i=1∑⌊DA⌋j=1∑⌊DB⌋d∣gcd(i,j)∑μ(d)d=1∑min(⌊DA⌋,⌊DB⌋)i=1∑⌊DA⌋j=1∑⌊DB⌋[d∣i,d∣j]μ(d)d=1∑min(⌊DA⌋,⌊DB⌋)⌊DdA⌋⌊DdB⌋μ(d)
直接 O ( n ) O(n) O(n)枚举 d d d即可
代码:
#include<bits/stdc++.h>
using namespace std;
#define N 1000000 + 200
int A,B,mxA,mxB,d;
int mu[N],pri[N];
long long pre[N];
bool flg[N];
void getmu()
{
int mx = 1000000,tot = 0;
mu[1] = 1;
for(int i = 2;i <= mx;i ++)
{
if(!flg[i])
pri[++ tot] = i,mu[i] = -1;
for(int j = 1;i * pri[j] <= mx && j <= tot;j ++)
{
flg[i * pri[j]] = 1;
if(i % pri[j] == 0)
{
mu[i * pri[j]] = 0;
break;
}
mu[i * pri[j]] = -mu[i];
}
}
}
int f(int l,int r)
{
return pre[r] - pre[l - 1];
}
void block(int st, int ed)
{
int R = 0;
long long ans = 0;
for (int i = st; i <= ed; i = R + 1)
{
R = min(mxB / (mxB / i),mxA / (mxA / i));
ans += 1ll * f(i,R) * (mxA / i) * (mxB / i);
}
printf("%lld\n",ans);
}
int main()
{
scanf("%d %d %d",&A,&B,&d);
mxA = A / d,mxB = B / d;
getmu();
for(int i = 1;i <= min(mxA,mxB);i ++)
pre[i] = pre[i - 1] + mu[i];
block(1,min(mxA,mxB));
}
P2522 [HAOI2011]Problem b
题意:
对于给出的 n ( n ≤ 50000 ) n(n\leq 50000) n(n≤50000)个询问,每次询问给出 a , b , c , d ( a , b , c , d ≤ 50000 ) a,b,c,d(a,b,c,d\leq50000) a,b,c,d(a,b,c,d≤50000),每次求有多少个数对 ( x , y ) (x,y) (x,y),满足 a ≤ x ≤ b a \leq x\leq b a≤x≤b, c ≤ y ≤ d c \leq y \leq d c≤y≤d,且 g c d ( x , y ) = k gcd(x,y) = k gcd(x,y)=k
solution:
题目要求的式子是:
∑
i
=
a
b
∑
j
=
c
d
[
g
c
d
(
i
,
j
)
=
=
k
]
\sum_{i = a}^{b}\sum_{j = c}^d[gcd(i,j) == k]
i=a∑bj=c∑d[gcd(i,j)==k]
可以稍微转化一下,使得原式为
∑
i
=
1
b
∑
j
=
1
d
[
g
c
d
(
i
,
j
)
=
=
k
]
−
∑
i
=
1
a
−
1
∑
j
=
1
d
[
g
c
d
(
i
,
j
)
=
=
k
]
−
∑
i
=
1
b
∑
j
=
1
c
−
1
[
g
c
d
(
i
,
j
)
=
=
k
]
+
∑
i
=
1
a
−
1
∑
j
=
1
c
−
1
[
g
c
d
(
i
,
j
)
=
=
k
]
\sum_{i = 1}^{b}\sum_{j = 1}^d[gcd(i,j) == k] - \sum_{i = 1}^{a - 1}\sum_{j = 1}^d[gcd(i,j) == k] - \sum_{i = 1}^{b}\sum_{j = 1}^{c - 1}[gcd(i,j) == k] + \sum_{i = 1}^{a - 1}\sum_{j = 1}^{c - 1}[gcd(i,j) == k]
i=1∑bj=1∑d[gcd(i,j)==k]−i=1∑a−1j=1∑d[gcd(i,j)==k]−i=1∑bj=1∑c−1[gcd(i,j)==k]+i=1∑a−1j=1∑c−1[gcd(i,j)==k]
将下式代入即可。
∑
i
=
1
A
∑
j
=
1
B
[
g
c
d
(
i
,
j
)
=
=
D
]
=
∑
d
=
1
m
i
n
(
⌊
A
D
⌋
,
⌊
B
D
⌋
)
⌊
A
D
d
⌋
⌊
B
D
d
⌋
μ
(
d
)
\sum_{i = 1}^{A}\sum_{j = 1}^B[gcd(i,j) == D]=\sum_{d = 1}^{min(\lfloor \frac{A}{D} \rfloor,\lfloor \frac{B}{D} \rfloor)}\lfloor \frac{A}{Dd} \rfloor \lfloor \frac{B}{Dd}\rfloor\mu(d)
i=1∑Aj=1∑B[gcd(i,j)==D]=d=1∑min(⌊DA⌋,⌊DB⌋)⌊DdA⌋⌊DdB⌋μ(d)
但是暴力枚举
d
d
d是会超时的,可以用整除分块来优化。
具体实现时,每次取 ⌊ A D d ⌋ \lfloor\frac{A}{Dd}\rfloor ⌊DdA⌋下一个右边界与 ⌊ B D d ⌋ \lfloor\frac{B}{Dd}\rfloor ⌊DdB⌋下一个右边界中较小的作为下一个有边界即可。
代码
#include<bits/stdc++.h>
using namespace std;
#define N 1000000 + 200
int A,B,C,D,k;
int mu[N],pri[N];
long long pre[N];
bool flg[N];
void getmu()
{
int mx = 1000000,tot = 0;
mu[1] = 1;
for(int i = 2;i <= mx;i ++)
{
if(!flg[i])
pri[++ tot] = i,mu[i] = -1;
for(int j = 1;i * pri[j] <= mx && j <= tot;j ++)
{
flg[i * pri[j]] = 1;
if(i % pri[j] == 0)
{
mu[i * pri[j]] = 0;
break;
}
mu[i * pri[j]] = -mu[i];
}
}
}
int f(int l,int r)
{
return pre[r] - pre[l - 1];
}
long long block(int st, int ed, int num1,int num2) {
int R = 0;//块的右边界
long long ans = 0;
for (int i = st; i <= ed; i = R + 1)
{
R = min(num1 / (num1 / i),num2 / (num2 / i));
ans += 1ll * f(i,R) * (num1 / i) * (num2 / i);
}
return ans;
}
void solve()
{
scanf("%d %d %d %d %d",&A,&B,&C,&D,&k);
int mxA = B / k,mnA = (A - 1) / k,mxB = D / k,mnB = (C - 1) / k;
long long ans = 0;
ans = block(1,min(mxA,mxB),mxA,mxB) - block(1,min(mxA,mnB),mxA,mnB) - block(1,min(mnA,mxB),mnA,mxB) + block(1,min(mnA,mnB),mnA,mnB);
printf("%lld\n",ans);
}
int main()
{
getmu();
for(int i = 1;i <= 100000;i ++)
pre[i] = pre[i - 1] + mu[i];
int T;
scanf("%d",&T);
while(T --)
solve();
}
P3327 [SDOI2015]约数个数和
题意:
设
d
(
x
)
d(x)
d(x)为
x
x
x的约数个数,
T
T
T组数据,每组数据给定
n
,
m
(
n
,
m
≤
50000
)
n,m(n,m\leq 50000)
n,m(n,m≤50000),求:
∑
i
=
1
n
∑
j
=
1
m
d
(
i
j
)
\sum^{n}_{i = 1}\sum^{m}_{j = 1}d(ij)
i=1∑nj=1∑md(ij)
solution:
有一个小结论: d ( i j ) = ∑ x ∣ i ∑ y ∣ j [ g c d ( x , y ) = 1 ] d(ij) = \sum_{x|i}\sum_{y|j}[gcd(x,y) = 1] d(ij)=∑x∣i∑y∣j[gcd(x,y)=1]
原式可化为下式
∑
i
=
1
n
∑
j
=
=
1
m
∑
x
∣
i
∑
y
∣
j
[
g
c
d
(
x
,
y
)
=
=
1
]
\sum^{n}_{i = 1}\sum^{m}_{j == 1}\sum_{x|i}\sum_{y|j}[gcd(x,y) == 1]
i=1∑nj==1∑mx∣i∑y∣j∑[gcd(x,y)==1]
改变求和顺序可得
∑
x
=
1
n
∑
y
=
1
m
⌊
n
x
⌋
⌊
m
y
⌋
[
g
c
d
(
x
,
y
)
=
=
1
]
=
∑
i
=
1
n
∑
j
=
1
m
⌊
n
i
⌋
⌊
m
j
⌋
[
g
c
d
(
i
,
j
)
=
=
1
]
\sum_{x = 1}^{n}\sum_{y = 1}^{m}\lfloor \frac{n}{x}\rfloor \lfloor \frac{m}{y}\rfloor [gcd(x,y) == 1]=\sum_{i = 1}^{n}\sum_{j = 1}^{m}\lfloor \frac{n}{i}\rfloor \lfloor \frac{m}{j}\rfloor [gcd(i,j) == 1]
x=1∑ny=1∑m⌊xn⌋⌊ym⌋[gcd(x,y)==1]=i=1∑nj=1∑m⌊in⌋⌊jm⌋[gcd(i,j)==1]
已知
[
g
c
d
(
i
,
j
)
=
1
]
=
ε
(
g
c
d
(
i
,
j
)
)
=
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
[gcd(i,j) = 1] = \varepsilon(gcd(i,j)) = \sum_{d|gcd(i,j)}\mu(d)
[gcd(i,j)=1]=ε(gcd(i,j))=d∣gcd(i,j)∑μ(d)
代入可得
∑
i
=
1
n
∑
j
=
1
m
⌊
n
i
⌋
⌊
m
j
⌋
∑
d
∣
g
c
d
(
i
,
j
)
μ
(
d
)
\sum_{i = 1}^{n}\sum_{j = 1}^{m}\lfloor \frac{n}{i}\rfloor \lfloor \frac{m}{j}\rfloor \sum_{d|gcd(i,j)}\mu(d)
i=1∑nj=1∑m⌊in⌋⌊jm⌋d∣gcd(i,j)∑μ(d)
转化一下可得
∑
d
=
1
m
i
n
(
n
,
m
)
∑
i
=
1
n
∑
j
=
1
m
⌊
n
i
⌋
⌊
m
j
⌋
[
d
∣
i
,
d
∣
j
]
μ
(
d
)
\sum_{d = 1}^{min(n,m)}\sum_{i = 1}^{n}\sum_{j = 1}^{m}\lfloor \frac{n}{i}\rfloor \lfloor \frac{m}{j}\rfloor \left[d|i,d|j\right]\mu(d)
d=1∑min(n,m)i=1∑nj=1∑m⌊in⌋⌊jm⌋[d∣i,d∣j]μ(d)
令
i
,
j
i,j
i,j枚举
d
d
d的倍数,可以将
[
d
∣
i
,
d
∣
j
]
[d|i,d|j]
[d∣i,d∣j]这个条件给去掉
∑
d
=
1
m
i
n
(
n
,
m
)
∑
i
=
1
⌊
n
d
⌋
∑
j
=
1
⌊
m
d
⌋
⌊
n
d
i
⌋
⌊
m
d
j
⌋
μ
(
d
)
\sum_{d = 1}^{min(n,m)}\sum_{i = 1}^{\lfloor \frac{n}{d}\rfloor}\sum_{j = 1}^{\lfloor \frac{m}{d}\rfloor}\lfloor \frac{n}{di}\rfloor \lfloor \frac{m}{dj}\rfloor \mu(d)
d=1∑min(n,m)i=1∑⌊dn⌋j=1∑⌊dm⌋⌊din⌋⌊djm⌋μ(d)
故原式等于
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
∑
i
=
1
⌊
n
d
⌋
⌊
n
d
i
⌋
∑
j
=
1
⌊
m
d
⌋
⌊
m
d
j
⌋
\sum_{d = 1}^{min(n,m)}\mu(d)\sum_{i = 1}^{\lfloor \frac{n}{d}\rfloor}\lfloor \frac{n}{di}\rfloor\sum_{j = 1}^{\lfloor \frac{m}{d}\rfloor} \lfloor \frac{m}{dj}\rfloor
d=1∑min(n,m)μ(d)i=1∑⌊dn⌋⌊din⌋j=1∑⌊dm⌋⌊djm⌋
令
f
(
x
)
=
∑
i
=
1
x
⌊
x
i
⌋
f(x) = \sum_{i = 1}^{x}\lfloor \frac{x}{i} \rfloor
f(x)=i=1∑x⌊ix⌋
由于
⌊
a
x
y
⌋
=
⌊
⌊
a
x
⌋
y
⌋
\lfloor\frac{a}{xy} \rfloor = \lfloor \frac{\lfloor \frac{a}{x} \rfloor}{y} \rfloor
⌊xya⌋=⌊y⌊xa⌋⌋
则原式等于
∑
d
=
1
m
i
n
(
n
,
m
)
μ
(
d
)
f
(
⌊
n
d
⌋
)
f
(
⌊
m
d
⌋
)
\sum_{d = 1}^{min(n,m)}\mu(d)f(\lfloor\frac{n}{d}\rfloor)f(\lfloor\frac{m}{d}\rfloor)
d=1∑min(n,m)μ(d)f(⌊dn⌋)f(⌊dm⌋)
f
f
f可以预处理后
O
(
1
)
O(1)
O(1)求得,整除分块处理,时间复杂度为
O
(
T
n
)
O(T\sqrt n)
O(Tn)
代码
#include<bits/stdc++.h>
using namespace std;
#define N 50000 + 200
long long mu[N];
int flg[N],pri[N];
long long f[N];
void getMu(int mx)
{
int tot = 0;
mu[1] = 1;
for (int i = 2; i <= mx; ++i)
{
if (!flg[i])
pri[++tot] = i, mu[i] = -1;
for (int j = 1; j <= tot && i * pri[j] <= mx; ++j)
{
flg[i * pri[j]] = 1;
if (i % pri[j] == 0) {
mu[i * pri[j]] = 0;
break;
}
mu[i * pri[j]] = -mu[i];
}
}
for(int i = 1;i <= mx;i ++)
mu[i] += mu[i - 1];
}
void block(int st, int ed, int num) {
int R = 0;
int ans = 0;
ed = min(ed, num);
for (int i = st; i <= ed; i = R + 1) {
R = min(ed,num / (num / i));
ans += (R - i + 1) * (num / i);
}
f[num] = ans;
}
void Block(int st, int ed, int num1,int num2)
{
int R = 0;
long long ans = 0;
for (int i = st; i <= ed; i = R + 1) {
R = min(num1 / (num1 / i),num2 / (num2 / i));
ans += (mu[R] - mu[i - 1]) * f[num1 / i] * f[num2 / i];
}
printf("%lld\n",ans);
}
void solve()
{
int n,m;
scanf("%d %d",&n,&m);
Block(1,min(n,m),n,m);
}
int main()
{
int T;
scanf("%d",&T);
getMu(50000);
for(int i = 1;i <= 50000;i ++)
block(1,i,i);
while(T --)
solve();
}
P3911 最小公倍数之和
题意:
给出 N N N个数 A 1 , A 2 . . . , A N A_1,A_2...,A_N A1,A2...,AN,求 ∑ i = 1 N ∑ j = 1 N l c m ( A i , A j ) , ( A i ≤ 5 e 4 , N ≤ 5 e 4 ) \sum_{i = 1}^{N}\sum_{j = 1}^{N}lcm(A_i,A_j),(A_i\leq5e4,N\leq5e4) ∑i=1N∑j=1Nlcm(Ai,Aj),(Ai≤5e4,N≤5e4)
solution:
令
c
i
c_i
ci表示
i
i
i出现的次数,
n
n
n为出现过的最大的数字
∑
i
=
1
n
∑
j
=
1
n
c
i
×
c
j
×
l
c
m
(
i
,
j
)
\sum_{i = 1}^{n}\sum_{j = 1}^{n} c_i\times c_j\times \mathrm{lcm}(i,j)
i=1∑nj=1∑nci×cj×lcm(i,j)
∑ i = 1 n ∑ j = 1 n c i × c j × i j g c d ( i , j ) \sum_{i = 1}^{n}\sum_{j = 1}^{n} c_i\times c_j\times \frac{ij}{\mathrm{gcd}(i,j)} i=1∑nj=1∑nci×cj×gcd(i,j)ij
∑ k = 1 n ∑ i = 1 n ∑ j = 1 n [ g c d ( i , j ) = = k ] × c i × c j × i × j k \sum_{k = 1}^{n}\sum_{i = 1}^{n}\sum_{j = 1}^{n}[gcd(i,j) == k] \times c_i\times c_j\times \frac{i\times j}{k} k=1∑ni=1∑nj=1∑n[gcd(i,j)==k]×ci×cj×ki×j
∑ k = 1 n ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ [ g c d ( i , j ) = = 1 ] × c i k × c j k × i × j × k \sum_{k = 1}^{n}\sum_{i = 1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j = 1}^{\lfloor\frac{n}{k}\rfloor}[gcd(i,j) == 1]\times c_{ik}\times c_{jk}\times i\times j\times k k=1∑ni=1∑⌊kn⌋j=1∑⌊kn⌋[gcd(i,j)==1]×cik×cjk×i×j×k
∑ k = 1 n ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) × c i k × c j k × i × j × k \sum_{k = 1}^{n}\sum_{i = 1}^{\lfloor\frac{n}{k}\rfloor}\sum_{j = 1}^{\lfloor\frac{n}{k}\rfloor}\sum_{d|gcd(i,j)}\mu(d) \times c_{ik}\times c_{jk}\times i\times j\times k k=1∑ni=1∑⌊kn⌋j=1∑⌊kn⌋d∣gcd(i,j)∑μ(d)×cik×cjk×i×j×k
∑ k = 1 n ∑ d = 1 ⌊ n k ⌋ ∑ i = 1 ⌊ n k ⌋ ∑ j = 1 ⌊ n k ⌋ [ d ∣ i , d ∣ j ] × μ ( d ) × c i k × c j k × i × j × k \sum_{k = 1}^{n}\sum_{d = 1}^{\lfloor\frac{n}{k}\rfloor} \sum_{i = 1}^{\lfloor\frac{n}{k}\rfloor} \sum_{j = 1}^{\lfloor\frac{n}{k}\rfloor} [d|i,d|j]\times \mu(d)\times c_{ik}\times c_{jk} \times i\times j \times k k=1∑nd=1∑⌊kn⌋i=1∑⌊kn⌋j=1∑⌊kn⌋[d∣i,d∣j]×μ(d)×cik×cjk×i×j×k
∑ k = 1 n ∑ d = 1 ⌊ n k ⌋ μ ( d ) × k × d 2 ∑ i = 1 ⌊ n k d ⌋ ∑ j = 1 ⌊ n k d ⌋ c i k d × c j k d × i × j \sum_{k = 1}^{n}\sum_{d = 1}^{\lfloor\frac{n}{k}\rfloor}\mu(d) \times k\times d^2 \sum_{i = 1}^{\lfloor\frac{n}{kd}\rfloor} \sum_{j = 1}^{\lfloor\frac{n}{kd}\rfloor} c_{ikd}\times c_{jkd}\times i\times j k=1∑nd=1∑⌊kn⌋μ(d)×k×d2i=1∑⌊kdn⌋j=1∑⌊kdn⌋cikd×cjkd×i×j
∑ k = 1 n ∑ d = 1 ⌊ n k ⌋ μ ( d ) × k × d 2 ( ∑ i = 1 ⌊ n k d ⌋ c i k d × i ) 2 \sum_{k = 1}^{n}\sum_{d = 1}^{\lfloor\frac{n}{k}\rfloor}\mu(d) \times k\times d^2 (\sum_{i = 1}^{\lfloor\frac{n}{kd}\rfloor} c_{ikd}\times i)^2 k=1∑nd=1∑⌊kn⌋μ(d)×k×d2(i=1∑⌊kdn⌋cikd×i)2
令
T
=
k
d
T= kd
T=kd
∑
k
=
1
n
∑
k
d
=
1
n
μ
(
d
)
×
k
×
d
2
(
∑
i
=
1
⌊
n
T
⌋
c
i
T
×
i
)
2
\sum_{k = 1}^{n}\sum_{kd = 1}^{n}\mu(d) \times k\times d^2 (\sum_{i = 1}^{\lfloor\frac{n}{T}\rfloor} c_{iT}\times i)^2
k=1∑nkd=1∑nμ(d)×k×d2(i=1∑⌊Tn⌋ciT×i)2
∑ T = 1 n T ( ∑ d ∣ T μ ( d ) × d ) ( ∑ i = 1 ⌊ n T ⌋ c i T × i ) 2 \sum_{T = 1}^{n}T(\sum_{d|T}\mu(d)\times d)(\sum_{i = 1}^{\lfloor\frac{n}{T}\rfloor} c_{iT}\times i)^2 T=1∑nT(d∣T∑μ(d)×d)(i=1∑⌊Tn⌋ciT×i)2
预处理第一个括号,第二个括号可以暴力算,时间复杂度是 O ( ∑ i = 1 n n i ) O(\sum_{i = 1}^{n}\frac{n}{i}) O(∑i=1nin),即 O ( n ln n ) O(n\ln n) O(nlnn)
代码:
#include<bits/stdc++.h>
using namespace std;
#define N 50000 + 200
int mu[N];
int flg[N],pri[N],cnt[N];
long long f[N];
long long ans;
void getMu(int mx)
{
int tot = 0;
mu[1] = 1;
for (int i = 2; i <= mx; ++i)
{
if (!flg[i])
pri[++tot] = i, mu[i] = -1;
for (int j = 1; j <= tot && i * pri[j] <= mx; ++j)
{
flg[i * pri[j]] = 1;
if (i % pri[j] == 0) {
mu[i * pri[j]] = 0;
break;
}
mu[i * pri[j]] = -mu[i];
}
}
for(int i = 1;i <= mx;i ++)
for(int j = i;j <= mx;j += i)
f[j] += mu[i] * i;
}
int main()
{
getMu(50000);
int n,mx = 0;
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
{
int x;
scanf("%d",&x);
cnt[x] ++;
mx = max(mx,x);
}
n = mx;
for(int i = 1;i <= n;i ++)
{
long long tmp = 0;
for(int j = 1;j <= n / i;j ++)
tmp += cnt[i * j] * j;
ans += i * f[i] * tmp * tmp;
}
printf("%lld\n",ans);
}