杭电多校第一场1011Function(莫比乌斯反演)
题目大意
求
∑
i
=
1
n
g
c
d
(
⌊
i
3
⌋
,
i
)
m
o
d
998244353
\sum_{i=1}^ngcd(\left\lfloor\sqrt[3]{i}\right\rfloor,i)\ mod\ 998244353
i=1∑ngcd(⌊3i⌋,i) mod 998244353
解题思路
以下极大一部分来自出题人的题解,仅仅对自己原来觉得有些跳得部分进行了补充,感谢出题人
令 r = ⌊ n 3 ⌋ − 1 r=\lfloor\sqrt[3]{n}\rfloor-1 r=⌊3n⌋−1
则原式等于
∑
i
=
1
n
gcd
(
⌊
i
3
⌋
,
i
)
=
∑
i
=
⌊
n
3
⌋
3
n
gcd
(
⌊
n
3
⌋
,
i
)
+
∑
a
=
1
r
∑
i
=
a
(
a
+
1
)
3
−
1
gcd
(
a
,
i
)
\begin{aligned} &\sum_{i=1}^n\gcd(\lfloor{\sqrt[3]{i}}\rfloor,i)\\ =&\sum_{i=\lfloor\sqrt[3]{n}\rfloor^3}^n\gcd(\lfloor\sqrt[3]{n}\rfloor,i)+\sum_{a=1}^{r}\sum_{i=a}^{(a+1)^3-1}\gcd(a,i) \end{aligned}
=i=1∑ngcd(⌊3i⌋,i)i=⌊3n⌋3∑ngcd(⌊3n⌋,i)+a=1∑ri=a∑(a+1)3−1gcd(a,i)
其中
∑
i
=
1
n
gcd
(
a
,
i
)
=
∑
d
∣
a
d
∑
i
=
1
n
[
gcd
(
a
,
i
)
=
d
]
=
∑
d
∣
a
d
∑
i
=
1
⌊
n
d
⌋
[
g
c
d
(
i
,
a
d
)
=
1
]
=
∑
d
∣
a
d
∑
i
=
1
⌊
n
d
⌋
∑
f
∣
g
c
d
(
i
,
a
d
)
μ
(
f
)
=
∑
d
∣
a
d
∑
f
∣
a
d
μ
(
f
)
⌊
n
d
f
⌋
=
∑
d
f
∣
a
⌊
n
d
f
⌋
∑
d
∣
d
f
d
μ
(
d
f
d
)
\begin{aligned} \sum_{i=1}^n\gcd(a,i) =&\sum_{d|a}d\sum_{i=1}^n[\gcd(a,i)=d]\\ =&\sum_{d|a}d\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}[gcd(i,\frac{a}{d})=1]\\ =&\sum_{d|a}d\sum_{i=1}^{\left\lfloor\frac{n}{d}\right\rfloor}\sum_{f|gcd(i,\frac{a}{d})}\mu(f)\\ =&\sum_{d|a}d\sum_{f|\frac{a}{d}}\mu(f)\left\lfloor\frac{n}{df}\right\rfloor\\ =&\sum_{df|a}\left\lfloor\frac{n}{df}\right\rfloor\sum_{d|df}d\mu(\frac{df}{d}) \end{aligned}
i=1∑ngcd(a,i)=====d∣a∑di=1∑n[gcd(a,i)=d]d∣a∑di=1∑⌊dn⌋[gcd(i,da)=1]d∣a∑di=1∑⌊dn⌋f∣gcd(i,da)∑μ(f)d∣a∑df∣da∑μ(f)⌊dfn⌋df∣a∑⌊dfn⌋d∣df∑dμ(ddf)
而根据迪利克雷卷积中
φ
=
μ
∗
e
\varphi=\mu*e
φ=μ∗e
有 ∑ d ∣ d f d μ ( d f d ) = ϕ ( d f ) \sum_{d|df}d\mu(\frac{df}{d})=\phi(df) ∑d∣dfdμ(ddf)=ϕ(df),接下来 a \sqrt a a枚举a的因数则可以得出第一部分的答案
第二个和式可以化为
∑
a
=
1
r
∑
T
∣
a
(
⌊
(
a
+
1
)
3
−
1
T
⌋
−
⌊
a
3
−
1
T
⌋
)
φ
(
T
)
=
∑
T
φ
(
T
)
∑
b
=
1
⌊
r
T
⌋
(
⌊
(
b
T
+
1
)
3
−
1
T
⌋
−
⌊
(
b
T
)
3
−
1
T
⌋
)
\begin{aligned} &\sum_{a=1}^{r}\sum_{T|a}(\lfloor\frac {(a+1)^3-1}T\rfloor-\lfloor\frac {a^3-1}T\rfloor)\varphi(T)\\ =&\sum_{T}\varphi(T)\sum_{b=1}^{\lfloor\frac {r}T\rfloor}(\lfloor\frac {(bT+1)^3-1}T\rfloor-\lfloor\frac {(bT)^3-1}T\rfloor)\\ \end{aligned}
=a=1∑rT∣a∑(⌊T(a+1)3−1⌋−⌊Ta3−1⌋)φ(T)T∑φ(T)b=1∑⌊Tr⌋(⌊T(bT+1)3−1⌋−⌊T(bT)3−1⌋)
而
⌊
(
b
T
+
1
)
3
−
1
T
⌋
−
⌊
(
b
T
)
3
−
1
T
⌋
=
⌊
b
3
T
2
+
3
b
2
T
+
3
b
⌋
−
⌊
b
3
T
2
−
1
T
⌋
=
3
T
b
2
+
3
b
+
1
\begin{aligned} &\lfloor\frac {(bT+1)^3-1}T\rfloor-\lfloor\frac {(bT)^3-1}T\rfloor\\ =&\lfloor b^3T^2+3b^2T+3b\rfloor-\lfloor b^3T^2-\frac 1T \rfloor\\ =&3Tb^2+3b+1 \end{aligned}
==⌊T(bT+1)3−1⌋−⌊T(bT)3−1⌋⌊b3T2+3b2T+3b⌋−⌊b3T2−T1⌋3Tb2+3b+1
因此
∑
a
=
1
r
∑
i
=
a
(
a
+
1
)
3
−
1
gcd
(
a
,
i
)
=
∑
T
=
1
r
φ
(
T
)
[
(
3
T
∑
b
=
1
⌊
r
T
⌋
b
2
)
+
(
3
∑
b
=
1
⌊
r
T
⌋
b
)
+
⌊
r
T
⌋
]
\begin{aligned} &\sum_{a=1}^{r}\sum_{i=a}^{(a+1)^3-1}\gcd(a,i)\\ =&\sum_{T=1}^r\varphi(T)[(3T\sum_{b=1}^{\lfloor\frac {r}T\rfloor}b^2)+(3\sum_{b=1}^{\lfloor\frac {r}T\rfloor}b)+\lfloor\frac {r}T\rfloor]\\ \end{aligned}
=a=1∑ri=a∑(a+1)3−1gcd(a,i)T=1∑rφ(T)[(3Tb=1∑⌊Tr⌋b2)+(3b=1∑⌊Tr⌋b)+⌊Tr⌋]
可以
O
(
n
3
)
O(\sqrt[3]n)
O(3n)求出。
总复杂度
O
(
T
n
3
)
O(T\sqrt [3]n)
O(T3n)。
n n n比较小的情况可能会出问题,注意要适当特判。也有其它的算法,只要是线性应该都是能过的。把 n 3 \sqrt[3]n 3n出到 1 0 7 10^7 107是为了卡非线性做法。
AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const double eps=1e-6;
const int mod=998244353;
const int size=1e7+5;
int p[size];bool prime[size];
int phi[size],tot;
int quick_pow(int a,int b){int ans=1;while(b){if(b&1)ans=1LL*ans*a%mod;a=1LL*a*a%mod;b>>=1;} return ans;}
int inv6,inv2;
template <class T>
void read(T &x) {
static char ch;static bool neg;
for(ch=neg=0;ch<'0' || '9'<ch;neg|=ch=='-',ch=getchar());
for(x=0;'0'<=ch && ch<='9';(x*=10)+=ch-'0',ch=getchar());
x=neg?-x:x;
}
void init()
{
inv6=quick_pow(6,mod-2);inv2=quick_pow(2,mod-2);
phi[1]=1;
for(int i=1;i<size;i++) prime[i]=true;
for(int i=2;i<size;i++)
{
if(prime[i])
p[++tot]=i,phi[i]=i-1;
for(int j=1;j<=tot&&p[j]*i<size;j++)
{
prime[i*p[j]]=false;
if(i%p[j]==0)
{
phi[i*p[j]]=phi[i]*p[j];
break;
}
else phi[i*p[j]]=phi[i]*phi[p[j]];
}
}
}
LL sum2(int n)
{
return 1LL*n*(n+1)%mod*(2*n+1)%mod*inv6%mod;
}
LL sum1(int n)
{
return 1LL*n*(1+n)%mod*inv2%mod;
}
int main()
{
init();
int t;
scanf("%d",&t);
while(t--)
{
__int128 n;
read(n);
LL a=(pow(n,1.0/3)+eps);
LL ans=0;
for(int i=1;i<=int(sqrt(a)+eps);i++)
{
LL t=i%mod;
LL tmp=(((__int128)(n/t)-((__int128)a*a*a-1)/t)%mod+mod)%mod;
if(a%i) continue;
ans=(ans+1LL*phi[t]%mod*tmp)%mod;
if(i*i==a) continue;
t=a/i%mod;
tmp=(((__int128)(n/t)-((__int128)a*a*a-1)/t)%mod+mod)%mod;
ans=(ans+1LL*phi[t]%mod*tmp)%mod;
}
LL r=a-1;
for(LL T=1;T<=r;T++)
{
ans=(ans+1LL*phi[T]*((3*T*sum2(r/T)%mod+3*sum1(r/T)+r/T)%mod)%mod)%mod;
}
printf("%lld\n",ans);
}
}