解题报告 P3768 简单的数学题

P3768 简单的数学题

给定 \(n,p\),求 :

\[\sum_{i=1}^n\sum_{j=1}^nijgcd(i,j)\quad (\mod p) \]

\(n\le 10^{10},5\times 10^{8} \le p\le 1.1\times 10^{10}\)

话不多述直接开始推式子。

\(gcd(i,j)=d\)

\[\begin{aligned} &\quad\sum_{i=1}^n\sum_{j=1}^nijgcd(i,j)\\ &=\sum_{d=1}^nd\sum_{i=1}^n\sum_{j=1}^nij[gcd(i,j)=d]\\ &=\sum_{d=1}^nd^3\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}ij[gcd(i,j)=1] \end{aligned} \]

设:

\[f(x)=\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}ij[gcd(i,j)=x] \]

\[F(x)=\sum_{x|i}f(i) \]

可以知道要求的是 \(f(1)\)

莫比乌斯反演得到:

\[\begin{aligned} &\quad f(x)=\sum_{x|i}\mu(\frac ix)F(i)\\ &\Rightarrow f(1)=\sum_{i=1}^{n/d}\mu(i)F(i)\\ &\because F(x)=\sum_{i=1}^{n/d}\sum_{j=1}^{n/d}ij[x|gcd(i,j)]\\ &\quad =x^2\sum_{i=1}^{n/dx}\sum_{j=1}^{n/dx}ij\\ &\quad =x^2(\sum_{i=1}^{n/dx}i)^2\\ &\therefore Ans=\sum_{d=1}^{n}d^3\sum_{i=1}^{n/d}\mu(i)i^2(\sum_{j=1}^{n/id}j)^2 \end{aligned} \]

\(T=id,sum(x)=\sum\limits_{i=1}^xi\) ,则 \(i=\frac Td\),。

\[\begin{aligned} Ans&=\sum_{T=1}^nsum(\frac nT)^2\sum_{d|T}d^3(\frac Td)^2\mu(\frac Td)\\ &=\sum_{T=1}^n sum(\frac nT)^2\cdot T^2\sum_{d|T}d\mu(\frac Td) \end{aligned} \]

联想到 \(\mu *id=\varphi\),我们可以得到:

\[Ans=\sum_{T=1}^nsum(\frac nT)^2\cdot T^2\varphi(T) \]

前面的 \(sum(\frac nT)^2\) 可以数论分块求,现在我们看看后面这块能不能求前缀和。

重新定义 \(f(x)=x^2\varphi(x)\),我们发现它是一个积性函数。

先设 \(S(n)=\sum\limits_{i=1}^nf(i)\),然后把杜教筛的式子摆在这里:

\[g(1)S(n)=\sum_{i=1}^n(f*g)(i)-\sum_{i=2}^ng(i)S(\frac ni) \]

我们想要快速求 \(\sum f*g\)

先把 \(\sum\limits_{i=1}^n(f*g)(x)\) 写开:

\[\sum\limits_{i=1}^n(f*g)(x)=\sum_{i=1}^n\sum_{d|i}g(\frac id)d^2\varphi(d) \]

我们考虑到 \(\varphi*I=id\ \text{,即}\ \sum\limits_{d|n}\varphi (d)=n\),就要将 \(d^2\) 因子消去,所以我们设 \(g(x)=x^2\)

\[\begin{aligned} &\quad \sum_{i=1}^n\sum_{d|i}g(\frac id)d^2\varphi(d)\\ &=\sum_{i=1}^ni^2\sum_{d|i}\varphi(d)\\ &=\sum_{i=1}^ni^3 \end{aligned} \]

由小学奥数知识它的值为 \(sum(n)^2\)

总之:

\[S(n)=\sum_{i=1}i^3-\sum_{i=2}i^2S(\frac ni) \]

答案是

\[Ans=\sum_{T=1}sum(\frac nT)^2\cdot T^2\varphi(T) \]

数论分块后,前面半截可以直接求,后面半截可以用杜教筛在非线性时间里面处理出来。

时间在 \(O(n^{\frac 34})\) 左右。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N=8000010;

ll nn=N-10,mod;

ll pr[N],phi[N],tot=0;
bool mp[N];
unordered_map<ll,ll> f;

void init()
{
	int n=nn;
	phi[1]=mp[1]=1ll;
	for(int i=2;i<=n;++i)
	{
		if(!mp[i]) pr[++tot]=i, phi[i]=i-1;
		for(int j=1;j<=tot&&pr[j]*i<=n;++j)
		{
			ll tmp=1ll*i*pr[j];
			mp[tmp]=1;
			if(i%pr[j]) phi[tmp]=1ll*phi[i]*phi[pr[j]]%mod;
			else {phi[tmp]=1ll*phi[i]*pr[j]%mod; break;}
		}
	}

	for(int i=2;i<=n;++i)
		phi[i]=(phi[i-1]+1ll*phi[i]*i%mod*i%mod)%mod;
}

ll inv2,inv6;
ll fpow(ll a,ll k,ll mod)
{
	ll res=1; a%=mod;
	while(k)
	{
		if(k&1) res=res*a%mod;
		a=a*a%mod; k>>=1;
	}
	return (res+mod)%mod;
}

ll sum(ll x)
{
	x%=mod;
	return x*(x+1)%mod*inv2%mod;
}

ll sumP(ll x)
{
	x%=mod;
	return x*(x+1)%mod*(x+x+1)%mod*inv6%mod;
}

ll GetSum(ll n)
{
	if(n<=nn) return phi[n];
	if(f[n]) return f[n];
	ll res=sum(n);
	res=res*res%mod;
	for(ll l=2,r;l<=n;l=r+1)
	{
		r=n/(n/l);
		ll T=(sumP(r)-sumP(l-1))%mod;
		res-=GetSum(n/l)*T%mod;
		res%=mod;
	}
	return f[n]=(res+mod)%mod;
}


int main()
{
#ifdef test
	freopen("wa.txt","w",stdout);
#endif
	ll n;
	scanf("%lld%lld",&mod,&n);
	nn=min(n,nn);
	inv2=fpow(2,mod-2,mod),inv6=fpow(6,mod-2,mod);
	init();
	ll ans=0;
	for(ll l=1,r;l<=n;l=r+1)
	{
		r=n/(n/l);
		ll Sum=sum(n/l);
		Sum=Sum*Sum%mod;
		ll T=(GetSum(r)-GetSum(l-1))%mod;
		ans+=Sum*T%mod;
		ans%=mod;
//		cout<<GetSum(r)<<" "<<r<<"\n";
	}
//	cout<<"-1 -1\n";
	printf("%lld",(ans+mod)%mod);
	return 0;
}

posted @ 2021-03-28 17:40  RemilaScarlet  阅读(63)  评论(0编辑  收藏  举报