「莫比乌斯反演 」学习记录

对于「学习记录」不含对知识点的解析,只是对本人写题的一个记录。

  • [ SDOI 2014 ]数表

    先不考虑 \(a\) 的情况,可以列出式子,不妨设 \(n<m\)

    \[ans= \sum\limits_{i=1}^n \sum\limits_{j=1}^m\sigma(\gcd(i,j)) \]

    \[ans = \sum\limits_{d=1}^{n} \sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor} \sum\limits_{j=1}^{\left\lfloor \frac{m}{d} \right\rfloor} \sigma(d)[\gcd(i,j)=1] \]

    \[ans = \sum\limits_{d=1}^{n} \sigma(d) \sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor} \sum\limits_{j=1}^{\left\lfloor \frac{m}{d} \right\rfloor} \sum\limits_{x|i,x|j} \mu(x) \]

    \[ans = \sum\limits_{d=1}^n \sigma(d) \sum\limits_{x=1}^{ \left\lfloor \frac{n}{d} \right\rfloor} \mu(x) \left\lfloor \dfrac{n}{dx} \right\rfloor \left\lfloor \dfrac{m}{dx} \right\rfloor \]

    \(t=dx\) ,然后替换进去

    \[ans = \sum\limits_{t=1}^n \left\lfloor \dfrac{n}{t} \right\rfloor \left\lfloor \dfrac{m}{t} \right\rfloor \sum\limits_{d|t} \sigma(d) \mu ( \left\lfloor \frac{t}{d} \right\rfloor) \]

    此时可以整除分块,后一段预处理出来后存一下前缀和 \(g_i = \sum\limits_{d|i} \sigma(d) \mu( \left\lfloor \dfrac{i}{d} \right\rfloor)\)

    现在考虑有 \(a\) 的限制,也就是 $ \sigma(d) \le a $ ,即我们只需要维护 \(g_i\)

    我们可以先离线一下询问,并且按照 \(a_i\) 来从小到大的排序。每次只需要动态对 \(g_i\) 进行修改,使本组的 \(g_i\) 满足 $ \sigma(d) \le a_i $,并在整除分块时查询区间和。此处可以选择树状数组。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll N=1e5+5;
const ll Mod=(1<<31);
struct Query{
	ll x,y,z,id;
}q[N],qi[N];
ll T,n,m,cnt,mu[N],d[N],sum[N],pri[N];
ll t[N],ans[N];
bool vis[N];
bool cmp(Query a,Query b){
	return a.z<b.z;
}
ll lowbit(ll x){return x&(-x);}
void modify(ll x,ll y){
	for(;x<=N-5;x+=lowbit(x))t[x]+=y;
}
ll query(ll x)
{	ll res=0;
	for(;x;x-=lowbit(x))res+=t[x];
	return res;
}
void init()
{	mu[1]=1;
	for(ll i=2;i<=N-5;i++)
	{	if(!vis[i])pri[++cnt]=i,mu[i]=-1;
		for(ll j=1;j<=cnt&&pri[j]*i<=N-5;j++)
		{	vis[i*pri[j]]=1;
			if(i%pri[j]==0)break;
			mu[i*pri[j]]=-mu[i];
		}
	}
	for(ll i=1;i<=N-5;i++)
		for(ll j=i;j<=N-5;j+=i)
			d[j]+=i;
	for(ll i=1;i<=N-5;i++)
		qi[i].id=i,qi[i].z=d[i];
	sort(qi+1,qi+1+(N-5),cmp);
}
ll solve(ll x,ll y)
{	ll res=0;
	for(ll l=1,r;l<=min(x,y);l=r+1)
	{	r=min((x/(x/l)),(y/(y/l)));
		res+=(x/l)*(y/l)*(query(r)-query(l-1));
	}
	return res;
}
int main()
{	//freopen("P3312_2.in","r",stdin);
	//freopen("ans.out","w",stdout);
	scanf("%lld",&T);
	for(ll i=1;i<=T;i++)
	{	scanf("%lld%lld%lld",&q[i].x,&q[i].y,&q[i].z);
		q[i].id=i;
	}
	sort(q+1,q+1+T,cmp);
	init();
	ll k=0;
	for(ll i=1;i<=T;i++)
	{	while(qi[k+1].z<=q[i].z&&k<N-5)
		{	ll x=qi[++k].id;
			for(ll j=1;j*x<=N-5;j++)modify(j*x,mu[j]*d[x]);
		}
		ans[q[i].id]=solve(q[i].x,q[i].y);
	}
	for(ll i=1;i<=T;i++)
		printf("%lld\n",ans[i]%Mod);
	return 0;
}

  • [国家集训队]Crash的数字表格

    题意:求 \(ans = \sum\limits_{i=1}^n \sum\limits_{j=1}^m \operatorname{lcm}(i,j)\)

    根据题意可以写出式子,不妨设 \(n<m\)

    \[\begin{aligned} ans &= \sum\limits_{i=1}^n \sum\limits_{j=1}^m \operatorname{lcm}(i,j) \\ &= \sum\limits_{i=1}^n \sum\limits_{j=1}^m \dfrac{i \cdot j}{\gcd(i,j)} \\ &= \sum\limits_{d=1}^n \sum\limits_{i=1}^n \sum\limits_{j=1}^m \dfrac{i \cdot j}{d}[\gcd(i,j)=d] \\ &= \sum\limits_{d=1}^n d \sum\limits_{i=1}^{\left\lfloor \dfrac{n}{d} \right\rfloor} \sum\limits_{j=1}^{\left\lfloor \dfrac{m}{d} \right\rfloor} i \cdot j [\gcd(i,j)=1] \\ &= \sum\limits_{d=1}^n d \sum\limits_{i=1}^{\left\lfloor \dfrac{n}{d} \right\rfloor} \sum\limits_{j=1}^{\left\lfloor \dfrac{m}{d} \right\rfloor} i \cdot j \sum\limits_{x|i,x|j} \mu(x) \end{aligned} \]

    枚举 \(k\)

    \[\begin{aligned} ans &= \sum\limits_{d=1}^{n} d \sum\limits_{k=1}^{\left\lfloor \dfrac{n}{d} \right\rfloor} \mu(k) \cdot k^2 \sum\limits_{i=1}^{\left\lfloor \dfrac{n}{d \cdot k} \right\rfloor} \sum\limits_{j=1}^{\left\lfloor \dfrac{m}{d \cdot k} \right\rfloor} i \cdot j \end{aligned} \]

    此时,跑整除分块,用等差数列预处理后面式子,复杂度为 $O( \sum\limits_{i=1}^{\sqrt{n}} \sqrt{\left\lfloor \dfrac{n}{i} \right\rfloor} +\sqrt{i} ) =O(\int_0^{\sqrt{n}} \sqrt{x} dx) =O(n^{0.75}) $​​​ 。已经可以通过本题。

    但我们考虑继续优化。

    \(s(x)=\sum\limits_{i=1}^x i, t=dk\) 。替换进去。

    \[\begin{aligned} ans &= \sum\limits_{d=1}^n d \sum\limits_{k=1}^{\left\lfloor \dfrac{n}{d} \right\rfloor} \mu(k) \cdot k^2 \cdot s(\left\lfloor \dfrac{n}{t} \right\rfloor) \cdot s(\left\lfloor \dfrac{m}{t} \right\rfloor) \end{aligned} \]

    枚举 \(t\)

    \[\begin{aligned} ans &= \sum\limits_{t=1}^n s(\left\lfloor \dfrac{n}{t} \right\rfloor) \cdot s(\left\lfloor \dfrac{m}{t} \right\rfloor) \sum\limits_{d|t} d \cdot \mu( \dfrac{t}{d} ) \cdot (\dfrac{t}{d})^2 \\ &= \sum\limits_{t=1}^n s(\left\lfloor \dfrac{n}{t} \right\rfloor) \cdot s(\left\lfloor \dfrac{m}{t} \right\rfloor) \sum\limits_{d|t} \dfrac{t}{d} \cdot \mu( d ) \cdot d^2 \\ &= \sum\limits_{t=1}^n s(\left\lfloor \dfrac{n}{t} \right\rfloor) \cdot s(\left\lfloor \dfrac{m}{t} \right\rfloor) \sum\limits_{d|t} t \cdot \mu( d ) \cdot d \end{aligned} \]

    不妨设 \(f(x)= \sum\limits_{d|x} \mu(d) \cdot d\)

    考虑 \(\gcd(a,b)=1\) 。有 \(f(a)= \sum\limits_{d|a} \mu(d) \cdot d,f(b)= \sum\limits_{d|b} \mu(d) \cdot d\)

    因为 \(\mu\) 是积性函数,且 \(a\)\(b\) 是互质的,质因子不同。

    则在 \(\gcd(a,b)=1\) 时, \(f(a \cdot b)=f(a) \cdot f(b)\) ,是积性函数。

    现在考虑 \(a \equiv 0 ( \mod b )\) ,且 \(b\) 为质数。则为 \(b\) 的因数一定为 \(a\) 的因数,且这几个 \(\mu(d) \cdot d\) 结果一定相同。而 \(a\) 中不为 \(b\) 的因数,质因数分解后次数一定大于 \(1\) ,也就是 \(\mu(d)=0\) 。所以可以得出 \(f(a)=f(b)\)

    这时已经可以线筛求出 \(f(x)\) 了。然后前缀和预处理时多乘上一个 \(t\) 。就可以整除分块直接求了。复杂度 \(O(\sqrt{n})\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const ll N=1e7+5;
const ll Mod=20101009;
ll n,m,cnt,ans,pri[N],mu[N],s[N],f[N];
bool vis[N];
void init()
{	mu[1]=f[1]=1;
	for(ll i=2;i<=N-5;i++)
	{	if(!vis[i])mu[i]=-1,pri[++cnt]=i,f[i]=(1-i+Mod)%Mod;
		for(ll j=1;i*pri[j]<=N-5&&j<=cnt;j++)
		{	vis[i*pri[j]]=1;
			if(i%pri[j]==0){f[i*pri[j]]=f[i];break;}
			mu[i*pri[j]]=-mu[i];
			f[i*pri[j]]=f[i]*f[pri[j]]%Mod;
		}
	}
	for(ll i=1;i<=N-5;i++)f[i]=(f[i-1]+f[i]*i%Mod)%Mod;
	for(ll i=1;i<=N-5;i++)s[i]=(s[i-1]+i)%Mod;
}
int main()
{	init();
	scanf("%lld%lld",&n,&m);
	for(ll l=1,r;l<=min(n,m);l=r+1)
	{	r=min(n/(n/l),m/(m/l));
		ans=(ans+(f[r]-f[l-1]+Mod)%Mod*s[n/l]%Mod*s[m/l]%Mod)%Mod;
	}
	printf("%lld\n",ans);
	return 0;
}

  • P3768 简单的数学题

    题意:求 \(\sum\limits_{i=1}^n \sum\limits_{j=1}^n i \cdot j \cdot \gcd(i,j)\)

    本题和[国家集训队]Crash的数字表格相似,或者说几乎一样 ,这里不再赘述。 其实就是懒

    \[ans= \sum\limits_{t=1}^n s( \left\lfloor \dfrac{n}{t} \right\rfloor)^2 \sum\limits_{d|t} t^2 \cdot d \cdot \mu(\left\lfloor \dfrac{t}{d} \right\rfloor) \]

    其中 \(s(x)=\sum\limits_{i=1}^x i\)

    但数据范围是 \(n \le 10^{10}\) ,所以 \(s(x)\) 直接用 \(\dfrac{n \times (n+1)}{2}\)

    \(\sum\limits_{d|t} t^2 \cdot d \cdot \mu(\left\lfloor \dfrac{t}{d} \right\rfloor)\) ,考虑用杜教筛处理。

    因为 \((id* \mu )(i)=\varphi(i)\) 。即 \(\sum\limits_{d|t} t^2 \cdot d \cdot \mu(\left\lfloor \dfrac{t}{d} \right\rfloor) = t^2 \varphi(t)\) 。令 \(f(i)=i^2 \varphi(i)\) ,求 \(S(n)=\sum\limits_{i=1}^n f(n)\)

    杜教筛:

    \[g(1)S(n)=\sum\limits_{i=1}^n (g* f)(i)-\sum\limits _ {i=2}^n g(i)S(\dfrac{n}{i}) \]

    \(g(x)=x^2\) 。则:

    \[S(n)=\sum\limits _ {i=1}^n (g*f)(i)-\sum\limits_{i=2}^n g(i)S(\dfrac{n}{i}) \]

    因为 \(\sum\limits_{d|n} \varphi(d) =n\) 。则:

    \[(g * f)(i)= \sum\limits_{d|i} f(d)g(\dfrac{i}{d}) = \sum\limits_{d|i} d^2 \varphi(i) (\dfrac{i}{d})^2 = i^2 \sum\limits_{d|i} \varphi(i) = i^3 \]

    \[S(n)= \sum\limits_{i=1}^n i^3 -\sum\limits_{i=2}^n i^2 S(\dfrac{n}{i}) \]

    因为 \(\sum\limits_{i=1}^n i^3 = (\sum\limits_{i=1}^n i)^2 = \dfrac{n(n+1)(2n+1)}{6}\) ,为 \(s(n)^2\)

    此时 \(S(n)\) 已经可以用杜教筛算出。前面用整除分块即可,复杂度 \(O(n^{\frac{2}{3}} + \sqrt{n})\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
const ll N=8e6+5;
ll n,Mod,ans,inv6,inv2,cnt,pri[N],pi[N];
bool vis[N];
map<ll,ll> mp;
ll qpow(ll x,ll k)
{	ll res=1;
	while(k)
	{	if(k&1)res=res*x%Mod;
		x=x*x%Mod;
		k>>=1;
	}
	return res;
}
void init()
{	vis[1]=1;pi[1]=1;
	for(ll i=2;i<=N-5;i++)
	{	if(!vis[i])pri[++cnt]=i,pi[i]=i-1;
		for(ll j=1;j<=cnt&&i*pri[j]<=N-5;j++)
		{	vis[i*pri[j]]=1;
			if(i%pri[j])pi[i*pri[j]]=1ll*pi[i]*pi[pri[j]]%Mod;
			else {pi[i*pri[j]]=pi[i]*pri[j]%Mod;break;}
		}
	}
	for(ll i=1;i<=N-5;i++)pi[i]=(pi[i-1]+pi[i]*i%Mod*i%Mod)%Mod;
}
ll getsum(ll x)
{	x%=Mod;
	return x*(x+1)%Mod*inv2%Mod;
}
ll getsump(ll x)
{	x%=Mod;
	return x*(x+1)%Mod*(x+x+1)%Mod*inv6%Mod;
}
ll getpi(ll x)
{	if(x<=N-5)return pi[x];
	if(mp[x])return mp[x];
	ll res=getsum(x);
	res=res*res%Mod;
	for(ll l=2,r;l<=x;l=r+1)
	{	r=x/(x/l);
		ll t=(getsump(r)-getsump(l-1))%Mod;
		res=(res-getpi(x/l)*t%Mod+Mod)%Mod;
	}
	return mp[x]=res;
}
int main()
{	scanf("%lld%lld",&Mod,&n);
	inv2=qpow(2,Mod-2);inv6=qpow(6,Mod-2);
	init();
	for(ll l=1,r;l<=n;l=r+1)
	{	r=n/(n/l);
		ll t=getsum(n/l),g=(getpi(r)-getpi(l-1))%Mod;
		t=t*t%Mod;g=(g+Mod)%Mod;
		ans=(ans+g*t%Mod)%Mod;
	}
	printf("%lld\n",ans);
	return 0;
}

  • [SDOI2017]数字表格

    题意:定义 \(f(0)=f(1)=1,f(n)=f(n-1)+f(n-2)\) ,求:

    \[\prod\limits_{i=1}^n \prod\limits_{j=1}^m f(\gcd(i,j)) \]

    不妨设 \(n<m\)

    \[\begin{aligned} ans &= \prod\limits_{d=1}^n \prod\limits_{i=1}^n \prod\limits_{j=1}^m f(d)[\gcd(i,j)=d] \\ &= \prod\limits_{d=1}^n f(d)^{\sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sum\limits_{j=1}^{\left\lfloor \frac{m}{d} \right\rfloor} [\gcd(i,j)=1]} \end{aligned} \]

    因为写的太丑了,所以单独拎出指数。

    \[\begin{aligned} \sum\limits_{i=1}^{\left\lfloor \frac{n}{d} \right\rfloor}\sum\limits_{j=1}^{\left\lfloor \frac{m}{d} \right\rfloor} [\gcd(i,j)=1]=\sum\limits_{k=1}^{\left\lfloor \frac{n}{d} \right\rfloor} \mu(k) \left\lfloor \frac{n}{dk} \right\rfloor \left\lfloor \frac{m}{dk} \right\rfloor \end{aligned} \]

    \(t=dk\)

    \[\begin{aligned} \sum\limits_{k=1}^{\left\lfloor \frac{n}{d} \right\rfloor} \mu(\left\lfloor \frac{n}{d} \right\rfloor) \left\lfloor \frac{n}{t} \right\rfloor \left\lfloor \frac{m}{t} \right\rfloor \end{aligned} \]

    \[\begin{aligned} ans &=\prod\limits_{d=1}^n f(d)^{\sum\limits_{k=1}^{\left\lfloor \frac{n}{d} \right\rfloor} \mu(\left\lfloor \frac{n}{d} \right\rfloor) \left\lfloor \frac{n}{t} \right\rfloor \left\lfloor \frac{m}{t} \right\rfloor} \\ &= \prod\limits _{t=1}^n \prod_{d|t} f(d)^{\mu(\left\lfloor \frac{n}{d} \right\rfloor) \left\lfloor \frac{n}{t} \right\rfloor \left\lfloor \frac{m}{t} \right\rfloor} \\ &= \prod\limits _{t=1}^n \prod_{d|t} \left( f(d)^{\mu(\left\lfloor \frac{n}{d} \right\rfloor) } \right) ^{\left\lfloor \frac{n}{t} \right\rfloor \left\lfloor \frac{m}{t} \right\rfloor} \end{aligned} \]

    此时我们可以对第一个 \(\prod\) 进行整除分块。那里面呢?

    考虑暴力算,复杂度 \(O(n)\)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const ll N=1e6+5;
const ll Mod=1e9+7;
ll T,n,m,cnt,ans,inv,pri[N],mu[N],f[N],g[N],F[N];
bool vis[N];
ll qpow(ll x,ll k)
{	ll res=1;
	while(k)
	{	if(k&1)res=res*x%Mod;
		x=x*x%Mod;
		k>>=1;
	}
	return res;
}
void init()
{	f[1]=g[1]=F[0]=F[1]=mu[1]=1;
	vis[1]=1;
	for(ll i=2;i<=N-5;i++)
	{	f[i]=(f[i-1]+f[i-2])%Mod;
		g[i]=qpow(f[i],Mod-2);F[i]=1;
		if(!vis[i])pri[++cnt]=i,mu[i]=-1;
		for(ll j=1;j<=cnt&&pri[j]*i<=N-5;j++)
		{	vis[i*pri[j]]=1;
			if(i%pri[j]==0)break;
			mu[i*pri[j]]=-mu[i];
		}
	}
	for(ll i=1;i<=N-5;i++)
	{	if(!mu[i])continue;
		for(ll j=i;j<=N-5;j+=i)
			F[j]=F[j]*(mu[i]==1?f[j/i]:g[j/i])%Mod;
	}
	for(ll i=2;i<=N-5;i++)F[i]=F[i]*F[i-1]%Mod;
}
int main()
{	init();
	scanf("%lld",&T);
	while(T--)
	{	scanf("%lld%lld",&n,&m);
		ans=1ll;inv=1ll;
		for(ll l=1,r;l<=min(n,m);l=r+1)
		{	r=min(n/(n/l),m/(m/l));
			inv=F[r]*qpow(F[l-1],Mod-2)%Mod;
			ans=ans*qpow(inv,(n/l)*(m/l))%Mod;
		}
		printf("%lld\n",ans);
	}
	return 0;
}

  • DIVCNT2 - Counting Divisors (square)

    题意:求 \(\sum\limits_{i=1}^n d(i^2)\) ,其中 \(d(x)\) 表示 \(x\) 的约数个数。

    约定,$\mathbf{1}(n)=\mathbf{id}^0(n)=1 $ 。

    不妨设 \(n=\prod\limits_{i=1}^k p_i^{a_i}\) ,则 \(n^2=\prod\limits_{i=1}^k p_i^{2a_i}\)

    \[\begin{aligned} d(i^2) &= \sum\limits_{u|i} \sum\limits_{v|i} [\gcd(u,v)=1] \\ &=\sum\limits_{x|i} \sum\limits_{u|x} [\gcd(u,\dfrac{x}{u})=1] \end{aligned} \]

    这一部分可以理解为,一个因数 \(x\) 的质因数要么给 \(u\) ,要么不给 \(u\) (若不全给即不影响结果)。所以一个质因数就有两种结果,即 \(2^{\omega(x)}\) ,其中 \(x\) 表示质因数个数。

    \[\begin{aligned} d(i^2) &= \sum\limits_{s \subseteq {1,2,...,k}} 2^{|s|} \times \prod\limits_{i \in s} a_i \\ &=\sum\limits _{d|n} \mu ^2(d) \end{aligned} \]

    \(f(n)= d(n^2),g(n)=2^ {\omega(n)},h(n)=\mu^2(n)\) ,则 $ f = g * \mathbf{1},g=h*\mathbf{1}$ 。

    所以 \(f=h * \mathbf{1} * \mathbf{1} = h * (\mathbf{1} * \mathbf{1})=h * d = \mu ^2(n)*d\) 。本题即求 \(f\) 的前缀和。

    也就是说我们要预处理 \(\mu^2(n)\)\(d\) 。首先 \(d\) 很显然:

    \[\sum\limits_{i=1}^nd(i)=\sum\limits_{i=1}^n \left\lfloor \dfrac{n}{i} \right\rfloor \]

    整除分块即可,复杂度 \(\mathcal{O}(\sqrt{n})\)

    考虑 \(\mu^2(n)\) ,不妨设 \(s(n)\) 为满足 \(k^2|n\) 的最大 \(k\) 。所以 \(d|s(n) \Leftrightarrow d^2 | n\) ,继续推导:

    \[\mu^2(n) = [s(n)=1] = \sum\limits_{d|s(n)} \mu(d) = \sum\limits_{d^2 | n}\mu(d) \]

    于是

    \[\sum\limits_{i=1}^n \mu^2(i) = \sum\limits_{i=1}^n \sum\limits_{d^2 | i} \mu(d)= \sum\limits_{i=1} ^ {\sqrt{n}} \mu(i) \cdot \left\lfloor \dfrac{n}{i^2} \right\rfloor \]

    这样就可以 \(\mathcal{O}(\sqrt{n})\) 算了。整除分块套整除分块,考虑预处理 \(n^{\frac{2}{3}}\) 的前缀和。 复杂度 \(\mathcal{O}(n^{\frac{2}{3}})\) ,可以通过本题。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=2e5+5,M=1e8+5;
ll n,mx,B,s[M],a[N];
int cnt,pri[M],smu[M];
char mu[M];
bool vis[M];
void init(int m)
{	s[1]=1;smu[1]=1;mu[1]=1;
	for(int i=2;i<=m;i++)
	{	if(!vis[i])pri[++cnt]=i,mu[i]=-1,smu[i]=1,s[i]=2;
		for(int j=1;j<=cnt&&i*pri[j]<=m;j++)
		{	vis[i*pri[j]]=1;
			if(i%pri[j]==0)
			{	s[i*pri[j]]=s[i]/(smu[i]+1)*(smu[i]+2);
				smu[i*pri[j]]=smu[i]+1;
				mu[i*pri[j]]=0;
				break;
			}
			s[i*pri[j]]=s[i]*2;
			smu[i*pri[j]]=1;
			mu[i*pri[j]]=-mu[i];
		}
	}
	for(int i=1;i<=m;i++)
	{	s[i]+=s[i-1];
		smu[i]=smu[i-1]+abs((int)mu[i]);
	}
}
ll getr(ll x)
{	if(x<=B)return s[x];
	ll res=0;
	for(ll l=1,r;l<=x;l=r+1)
	{	r=(x/(x/l));
		res+=(r-l+1)*(x/l);
	}
	return res;
}
ll getsmu(ll x)
{	if(x<=B)return smu[x];
	ll res=0;
	for(ll i=1;i*i<=x;i++)
		if(mu[i])res+=mu[i]*(x/(i*i));
	return res;
}
void solve(ll nn)
{	ll m=sqrt(nn),pre=smu[m],tt,ans=0;
	for(int i=1;i<=m;i++)
		if(mu[i])ans+=getr(nn/i);
	for(ll l=m+1,r;l<=nn;l=r+1)
	{	r=(nn/(nn/l));
		tt=getsmu(r);
		ans+=(tt-pre)*getr(nn/l);
		pre=tt;
	}
	printf("%lld\n",ans);
}
int main()
{	scanf("%lld",&n);
	for(int i=1;i<=n;i++)
	{	scanf("%lld",&a[i]);
		mx=max(mx,a[i]);
	}
	if(mx<=10000)B=10000;
	else B=pow(1000000000000,2.0/3.0);
	init(B);
	for(int i=1;i<=n;i++)
		solve(a[i]);
	return 0;
}

\[\text{by Rainy7} \]

posted @ 2021-08-21 23:11  Rainy7  阅读(164)  评论(1编辑  收藏  举报