题目:求
i=1∑ngcd(3i
,i),n≤1e21
本文学习了连接这位大佬的博客,本文仅仅是理解他博客的公式后自己的推公式过程
直接求显然不可以,推一波公式化简一下。
前置公式:
(1)莫比乌斯公式:若
g(x)=x∣d∑f(d),则
f(x)=x∣d∑μ(xd)g(d)
(2)欧拉函数与莫比乌斯函数的一个关系式:
ϕ(n)=
d∣n∑μ(d)⋅⌊dn⌋ ;
(3)
i=1∑ni2=6n(n+1)(2n+1)
(4)
i=1∑ni=2n(n+1)
(5)
若a∣b,b∣c,则a∣c
正式推公式:
i=1∑ngcd(3i
,i)
=i=⌊3n
⌋3∑ngcd(⌊3n
⌋,i)+a=1∑⌊3n
⌋−1i=a3∑(a+1)3−1gcd(a,i)
我们看到求解的问题被分为两部分,但前后两部分都有求
i=l∑rgcd(a,i)把这部分单独拿出来求
定义
f(l,r,x)=i=l∑r[gcd(i,a)==x]
则
i=l∑rgcd(a,i)=x∣a∑xi=l∑r[gcd(i,a)==x]=x∣a∑xf(l,r,x)
对
f进行反演一波,构造
g(l,r,x)=x∣d∑f(l,r,d)=x∣d∑f(l,r,d)=x∣d∑i=l∑r[gcd(i,a)==d]
由公式(5)可知
i只要满足
x∣gcd(i,a)即为有效贡献,所以
g(l,r,x)=i=l∑r[x∣gcd(i,a)]=⌊xr⌋−⌊xl−1⌋,注意这里要满足
x∣a,
因为如果
x不是a的因子的话,g(l,r,x)=0
由公式(1)可知
f(l,r,x)=x∣d∑μ(xd)g(l,r,d)
因为如果
x不是a的因子的话,g(l,r,x)=0
所以
f(l,r,x)==x∣d,d∣a∑μ(xd)(⌊dr⌋−⌊dl−1⌋)
所以
i=l∑rgcd(a,i)=x∣a∑xx∣d,d∣a∑μ(xd)(⌊dr⌋−⌊dl−1⌋)=d∣a∑(⌊dr⌋−⌊dl−1⌋)x∣d∑xμ(xd)=d∣a∑(⌊dr⌋−⌊dl−1⌋)ϕ(d)
最后一步就是把
x和d的顺序调换,本来是先x∣a再x∣d,d∣a转成先
d∣a,再x∣d
到这里就可以
O(a
)求i=l∑rgcd(a,i)了,所以求解
i=⌊3n
⌋3∑ngcd(⌊3n
⌋,i)的复杂度为
O(6n
)
对于后一段,直接求复杂度仍然很高,需要继续化简
a=1∑⌊3n
⌋−1i=a3∑(a+1)3−1gcd(a,i)=a=1∑⌊3n
⌋−1d∣a∑(⌊d(a+1)3⌋−⌊da3−1⌋)ϕ(d)=d=1∑⌊3n
⌋−1ϕ(d)i=1∑⌊d⌊3n
⌋−1⌋⌊d(di+1)3⌋−⌊ddi3−1⌋)=d=1∑⌊3n
⌋−1i=1∑⌊d⌊3n
⌋−1⌋(3i2d+3i+1)ϕ(d)
令
y=⌊d⌊3n
⌋−1⌋且又(4)(5)得后半段为
a=1∑⌊3n
⌋−1i=a3∑(a+1)3−1gcd(a,i)=d=1∑⌊3n
⌋−1ϕ(a)(3∗d∗6y(y+1)(2y+1)+32y(y+1)+y)
对
y进行分块处理,整体复杂度也为O(
6n
),对
ϕ(i)和iϕ(i)前缀和预处理为O(3n
)
所以这道题可以在复杂度
O(3n
)下完成。
代码因为找不到错误,对拍对着对着跟原博主的代码越来越像。
ac代码:
#include<bits/stdc++.h>
#define db double
#define ui unsigned int
#define ll long long
#define ull unsiged ll
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l)for(int i=r;i>=l;i--)
#define file(x) freopen(#x".in","w",stdout);
#define bug(x) cerr<<#x<<": "<<x<<endl
typedef __int128 int128;
using namespace std;
const int MX = 1e7 + 7;
const int mod=998244353;
ll modulo(ll num, ll MOD = mod) { return ((num%MOD) + MOD) % MOD; }
ll power(ll b, ll e, ll MOD = mod) { ll ans = 1; while (e) { if (e % 2) ans = (ans*b) % MOD; b = (b*b) % MOD; e /= 2; } return ans; }
ll inv(ll num, ll MOD = mod) { return power(modulo(num), MOD - 2, MOD); }
ll gcd(ll a, ll b) { return ((b == 0) ? a : gcd(b, a%b)); }
ll phi[MX];
ll pri[MX],inv2,inv6,iphi[MX],phisum[MX];
bool isp[MX];
int tmp=0;
struct Istream {
template <class T>
Istream &operator >>(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;
return *this;
}
}fin;
struct Ostream {
template <class T>
Ostream &operator <<(T x) {
x<0 && (putchar('-'),x=-x);
static char stack[233];static int top;
for(top=0;x;stack[++top]=x%10+'0',x/=10);
for(top==0 && (stack[top=1]='0');top;putchar(stack[top--]));
return *this;
}
Ostream &operator <<(char ch) {
putchar(ch);
return *this;
}
}fout;
void pre_phi()
{
isp[0]=isp[1]=false;
phi[1]=1;
for(int i=2;i<MX;i++)
{
if(!isp[i])
{
pri[++tmp]=i;
phi[i]=i-1;
}
for(ll j=1;i*pri[j]<MX&&j<=tmp;j++)
{
int ans=i*pri[j];
isp[ans]=true;
if(i%pri[j])
{
phi[ans]=phi[i]*(pri[j]-1);
}
else {
phi[ans]=phi[i]*pri[j];
break;
}
}
}
phisum[1]=1,iphi[1]=1;
for(int i=2;i<MX;i++)
{
iphi[i]=(iphi[i-1]+1ll*i*phi[i]%mod)%mod;
phisum[i]=(phisum[i-1]+phi[i])%mod;
}
}
int128 get_n3(int128 n)
{
int128 l=0,r=1e8,res=1,mid;
while(l<=r)
{
mid=(l+r)/2;
if(int128(mid*mid*mid)<=n)res=mid,l=mid+1;
else r=mid-1;
}
return res;
}
int main()
{
inv2=inv(2),inv6=inv(6);
int t;
pre_phi();
fin>>t;
while(t--){
int128 n;
fin>>n;
ll ans=0;
int128 n3=get_n3(n);
int128 m=n3*n3*n3;
for(ll i=1;i*i<=n3;i++)
{
if(n3%i==0)
{
ans=ans+phi[i]*(n/i-(m-1)/i)%mod;
ll t=n3/i;
if(i*i!=n3)
ans+=phi[t]*(n/t-(m-1)/t)%mod;
ans=ans%mod;
}
}
n3--;
ll j,res;
for(ll i=1;i<=n3;i=j+1)
{
res=n3/i;
j=n3/res;
ans=ans+3*(iphi[j]-iphi[i-1]+mod)%mod*res%mod*(res+1)%mod*(2*res+1)%mod*inv6%mod;
ans=ans+(phisum[j]-phisum[i-1]+mod)%mod*(3*res*(res+1)%mod*inv2%mod+res)%mod;
ans=ans%mod;
}
fout<<ans<<'\n';
//cout<<ans<<endl;
}
}