Loading

P3768 简单的数学题 题解

P3768 简单的数学题

\[\sum_{i=1}^{n} \sum_{j=1}^{n} ijgcd(i,j)\\ =\sum_{d=1}^{n} d^3 \sum_{i=1}^{\frac{n}{d}} \sum_{j=1}^{\frac{n}{d}} ij[gcd(i,j)==1]\\ =\sum_{d=1}^{n} d^3 \sum_{x=1}^{\frac{n}{d}}\mu(x)x^2\sum_{i=1}^{\frac{n}{xd}} \sum_{j=1}^{\frac{n}{xd}} ij\\g(x)=(\sum_{i=1}^x i)^2\\ =\sum_{d=1}^{n} d^3 \sum_{x=1}^{\frac{n}{d}}\mu(x)x^2g(\dfrac{n}{xd})\\ =\sum_{d=1}^{n} d^3 \sum_{T=1,d\mid T}^{n}\mu(\dfrac{T}{d})(\dfrac{T}{d})^2 g(\dfrac{n}{T})\\ =\sum_{T=1}^{n}g(\dfrac{n}{T})\sum_{d=1,d\mid T}^{n}d^3 \mu(\dfrac{T}{d})(\dfrac{T}{d})^2\\ =\sum_{T=1}^{n}g(\dfrac{n}{T})T^2\sum_{d=1,d\mid T}^{n}\times d \mu(\dfrac{T}{d})\\ =\sum_{T=1}^{n}g(\dfrac{n}{T})T^2\varphi(T)\\ \]

发现需要快速求出 \(S(n)=\sum\limits_{i=1}^{n}i^2\varphi(i)\), 而且要亚线性,我只会杜教筛。套路式子:

\[g(1)S(n)=(f*g)(n)-\sum_{d=2}^n g(d)S(\dfrac{n}{d}) \]

\[ f=\sum_{i=1}^{n}i^2\varphi(i)\\ g=id^2\\ (f*g)(n)=\sum_{d|n}d^2\varphi(d)(\dfrac{n}{d})^2=n^2\sum_{d|n}\varphi(n)=n^3\\ \sum_{i=1}^{n} (f*g)(i) =\sum_{i=1}^{n}i^3\\ S(n)=\sum_{i=1}^n i^3-\sum_{d=2}^n i^2 \sum_{j=1}^{\frac{n}{i}}\varphi(j)*j^2 \]

推到这里就可以杜教筛了

用杜教筛筛 \(\varphi(i)i^2\) 的前缀和,外层整除分块,完结撒花。

提供一组强样例供调试

Input
1000000007 9786510294 
Output
27067954
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef double db;
#define pb(x) push_back(x)
#define mkp(x,y) make_pair(x,y)
//#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
//char buf[1<<21],*p1=buf,*p2=buf;
inline int read() {
	int x=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-')f=-1;ch=getchar();}
	while(isdigit(ch))x=x*10+(ch^48),ch=getchar();
	return x*f;
}
int mod,ans,inv6,inv2;
LL n;
const int N=8000005;
const int C=N-5;
inline int qpow(int n,int k){
	int res=1;
	while(k){
		if(k&1)res=1ll*res*n%mod;
		n=1ll*n*n%mod,k>>=1; 
	}
	return res;
}
int pri[N],cnt,phi[N],sum[N];
bool vis[N];
void Sieve(const int&N){
	phi[1]=1;
	for(int i=2;i<=N;++i){
		if(!vis[i])pri[++cnt]=i,phi[i]=i-1;
		for(int j=1;j<=cnt&&i*pri[j]<=N;++j){
			vis[i*pri[j]]=1;
			if(i%pri[j]==0){phi[i*pri[j]]=1ll*phi[i]*pri[j]%mod;break;}
			else phi[i*pri[j]]=1ll*phi[i]*phi[pri[j]]%mod;
		}
	}
	for(int i=1;i<=N;++i)sum[i]=(1ll*i*i%mod*phi[i]%mod+sum[i-1])%mod;
}
int f1(LL x){//一次方和 
	return x%=mod,1ll*x*(x+1)%mod*inv2%mod; 
}
int f2(LL x){//二次方和 
	x%=mod;
	LL res=1ll*x*(x+1)%mod*(2*x+1)%mod*inv6%mod;
	return res;
}
int f3(LL x){//三次方和 
	int t=f1(x%mod);
	return 1ll*t*t%mod;
}
unordered_map<LL,int>mp;
int djs(LL x){
	if(x<=C)return sum[x];
	if(mp[x])return mp[x];
	int res=f3(x);
	for(LL l=2,r;l<=x;l=r+1)
		r=x/(x/l),res=(res-1ll*(f2(r)-f2(l-1))*djs(x/l)%mod)%mod;
	return mp[x]=(res+mod)%mod;
}
signed main(){
	scanf("%d%lld",&mod,&n),Sieve(min(n,1ll*C));
	inv6=qpow(6,mod-2),inv2=qpow(2,mod-2);
	for(LL l=1,r;l<=n;l=r+1){
		r=n/(n/l),ans=(ans+1ll*(djs(r)-djs(l-1))*f3(n/l)%mod)%mod;
	} 
	printf("%d\n",(ans+mod)%mod);
	return 0;
}
posted @ 2020-09-27 15:18  zzctommy  阅读(127)  评论(0编辑  收藏  举报