需要求
∑ i = 1 n gcd ( ⌊ i 3 ⌋ , i ) m o d    998244353 n = 1 0 21 \sum_{i=1}^n\gcd(\lfloor{\sqrt[3]{i}}\rfloor,i)\mod 998244353 \quad n = 10^{21} i=1∑ngcd(⌊3i⌋,i)mod998244353n=1021
思路
令 m = ⌊ n 3 ⌋ − 1 m=\lfloor \sqrt[3]{n} \rfloor-1 m=⌊3n⌋−1,
则 ∑ i = 1 n g c d ( f l o o r ( i 3 ) , i ) = ∑ i = 1 m ∑ j = i 3 ( i + 1 ) 3 − 1 g c d ( i , j ) + ∑ i = ( m + 1 ) 3 n g c d ( m + 1 , i ) \sum_{i=1}^{n}gcd(floor(\sqrt[3]{i}),i) = \sum_{i=1}^{m}\sum\limits_{j=i^{3}}^{(i+1)^{3}-1}gcd(i,j) \quad + \quad \sum\limits_{i=(m+1)^{3}}^{n}gcd(m+1,i) ∑i=1ngcd(floor(3i),i)=∑i=1mj=i3∑(i+1)3−1gcd(i,j)+i=(m+1)3∑ngcd(m+1,i)
考虑一个函数(前缀和,差分后即为上面部分所求,这个想法也比较自然),
f
(
n
)
=
∑
i
=
1
n
g
c
d
(
m
,
i
)
f(n) = \sum_{i=1}^ngcd(m,i)
f(n)=∑i=1ngcd(m,i)
f
(
n
)
=
∑
i
=
1
n
g
c
d
(
m
,
i
)
=
∑
i
=
1
n
∑
d
∣
g
c
d
(
m
,
i
)
ϕ
(
d
)
=
∑
d
∣
m
ϕ
(
d
)
∗
⌊
n
d
⌋
f(n) = \sum_{i=1}^ngcd(m,i) \\ = \sum_{i=1}^n \sum_{d|gcd(m,i)}\phi(d) \\ = \sum_{d|m} \phi(d)*\left \lfloor \frac{n}{d} \right \rfloor
f(n)=i=1∑ngcd(m,i)=i=1∑nd∣gcd(m,i)∑ϕ(d)=d∣m∑ϕ(d)∗⌊dn⌋
则 :
注意下面的,
m
=
⌊
n
3
⌋
−
1
m=\lfloor \sqrt[3]{n} \rfloor-1
m=⌊3n⌋−1
∑
i
=
1
n
g
c
d
(
f
l
o
o
r
(
i
3
)
,
i
)
=
∑
i
=
1
m
∑
j
=
i
3
(
i
+
1
)
3
−
1
g
c
d
(
i
,
j
)
+
∑
i
=
(
m
+
1
)
3
n
g
c
d
(
m
+
1
,
i
)
=
∑
i
=
1
m
∑
d
∣
i
ϕ
(
d
)
∗
[
⌊
(
i
+
1
)
3
−
1
d
⌋
−
⌊
i
3
−
1
d
⌋
]
+
∑
d
∣
m
+
1
ϕ
(
d
)
∗
[
⌊
n
d
⌋
−
⌊
(
m
+
1
)
3
−
1
d
⌋
]
=
∑
d
=
1
m
ϕ
(
d
)
∗
∑
i
=
1
⌊
m
/
d
⌋
[
⌊
(
i
d
+
1
)
3
−
1
d
⌋
−
⌊
(
i
d
)
3
−
1
d
⌋
]
+
∑
d
∣
m
+
1
ϕ
(
d
)
∗
[
⌊
n
d
⌋
−
⌊
(
m
+
1
)
3
−
1
d
⌋
]
=
∑
d
=
1
m
ϕ
(
d
)
∗
∑
i
=
1
⌊
m
/
d
⌋
[
3
d
i
2
+
3
i
+
1
(
注
意
这
里
是
下
取
整
)
]
+
∑
d
∣
m
+
1
ϕ
(
d
)
∗
[
⌊
n
d
⌋
−
⌊
(
m
+
1
)
3
−
1
d
⌋
]
\sum_{i=1}^{n}gcd(floor(\sqrt[3]{i}),i) = \sum_{i=1}^{m}\sum\limits_{j=i^{3}}^{(i+1)^{3}-1}gcd(i,j) \quad + \quad \sum\limits_{i=(m+1)^{3}}^{n}gcd(m+1,i) \\ = \sum_{i=1}^{m}\sum_{d|i}\phi(d)*\left [ \left \lfloor \frac{(i+1)^3 -1}{d} \right \rfloor - \left \lfloor \frac{i^3-1}{d} \right \rfloor \right ] \quad + \quad \sum_{d|m+1}\phi(d)*\left [ \left \lfloor \frac{n}{d} \right \rfloor - \left \lfloor \frac{(m+1)^3-1}{d} \right \rfloor \right ] \\ = \sum_{d=1}^{m}\phi(d)*\sum_{i=1}^{ \lfloor m/d \rfloor}\left [ \left \lfloor \frac{(id+1)^3 -1}{d} \right \rfloor - \left \lfloor \frac{(id)^3-1}{d} \right \rfloor \right ] \quad + \quad \sum_{d|m+1}\phi(d)*\left [ \left \lfloor \frac{n}{d} \right \rfloor - \left \lfloor \frac{(m+1)^3-1}{d} \right \rfloor \right ] \\ = \sum_{d=1}^{m}\phi(d)*\sum_{i=1}^{ \lfloor m/d \rfloor}\left [ 3di^2 + 3i + 1(注意这里是下取整) \right ] \quad + \quad \sum_{d|m+1}\phi(d)*\left [ \left \lfloor \frac{n}{d} \right \rfloor - \left \lfloor \frac{(m+1)^3-1}{d} \right \rfloor \right ]
i=1∑ngcd(floor(3i),i)=i=1∑mj=i3∑(i+1)3−1gcd(i,j)+i=(m+1)3∑ngcd(m+1,i)=i=1∑md∣i∑ϕ(d)∗[⌊d(i+1)3−1⌋−⌊di3−1⌋]+d∣m+1∑ϕ(d)∗[⌊dn⌋−⌊d(m+1)3−1⌋]=d=1∑mϕ(d)∗i=1∑⌊m/d⌋[⌊d(id+1)3−1⌋−⌊d(id)3−1⌋]+d∣m+1∑ϕ(d)∗[⌊dn⌋−⌊d(m+1)3−1⌋]=d=1∑mϕ(d)∗i=1∑⌊m/d⌋[3di2+3i+1(注意这里是下取整)]+d∣m+1∑ϕ(d)∗[⌊dn⌋−⌊d(m+1)3−1⌋]
因此可以计算 ,时间复杂度
O
(
1
e
7
+
T
∗
(
1
e
7
+
1
e
7
)
O(1e7 + T*(1e7+\sqrt{1e7})
O(1e7+T∗(1e7+1e7) 其中
T
T
T为数据组数,最左边的
1
e
7
1e7
1e7为预处理欧拉函数的时间。
本题的关键在于推导的倒数第二行变换贡献,从枚举 i i i变为枚举 d d d,使得复杂度降了下来
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int128 lll;
const int mod = 998244353;
const int inv2 = 499122177;
const int inv6 = 166374059;
const int maxn=1e7+10;
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;
}
lll n;
int tot;
bool valid[maxn];//is prime or not
int phi[maxn];// phi
int ans[maxn];// prime
void getprime(int n)
{
tot=0;
phi[1]=1;
memset(valid,true,sizeof(valid));
for(int i=2;i<=n;++i){
if(valid[i]){
tot++;
ans[tot]=i;
phi[i]=i-1;//i为素数
}
//下面的主角是小于等于i的每个质数
for(int j=1;(j<=tot) && (i*ans[j]<=n);++j){
valid[i*ans[j]]=false;
if(i%ans[j]==0){//ans[j]是i的素因子
phi[i*ans[j]]=phi[i]*ans[j];
break;//如果整除就break;
}
else phi[i*ans[j]]=phi[i]*(ans[j]-1);
}
}
}
lll pow3(lll x)
{
return x*x*x;
}
//n(n+1)(2n+1)/6
ll solve(int d, ll m){
ll up = m/d;
ll ans1 = (1+up)*up%mod*inv2%mod;
ll ans2 = d*up%mod*(up+1)%mod*(2*up+1)%mod*inv6%mod;
return ((ans1+ans2)*3 + up)%mod;
}
int main()
{
getprime(1e7);
int t;
cin>>t;
while(t--)
{
read(n);
int m = pow(n,1.0/3) - 1e5;
for(;pow3(m)<=n;m++);
m-=2;
ll ans = 0;
for(int d=1;d<=m;++d){
ans=(ans + 1LL*phi[d]*solve(d,m)%mod)%mod;
}
ll res = 0;
int now=m+1;
for(int i=1;i*i<=now;++i){
if(now%i==0){//i now/i
res = (res + 1LL*phi[i]*((n/i-(pow3(m+1)-1)/i)%mod) )%mod;
if(i*i!=now) res = (res + 1LL*phi[now/i]*((n/(now/i)-(pow3(m+1)-1)/(now/i))%mod) )%mod;
}
}
ans = (ans + res)%mod;
cout<<ans<<endl;
}
return 0;
}