[LUOGU3768]简单的数学题

Posted by Dispwnl on August 30, 2018

题目

题目描述

由于出题人懒得写背景了,题目还是简单一点好。

输入一个整数n和一个整数p,你需要求出$(\sum_{i=1}^n\sum_{j=1}^n ij\gcd(i,j))\mod p$,其中gcd(a,b)表示a与b的最大公约数。

输入输出格式

输入格式:

一行两个整数p、n。

输出格式:

一行一个整数$(\sum_{i=1}^n\sum_{j=1}^n ij\gcd(i,j))\mod p$。

输入输出样例

输入样例#1:

998244353 2000

输出样例#1:

883968974

说明

对于20%的数据,$n \leq 1000$。

对于30%的数据,$n \leq 5000$。

对于60%的数据,$n \leq 10^6$,时限1s。

对于另外20%的数据,$n \leq 10^9$,时限3s。

对于最后20%的数据,$n \leq 10^{10}$,时限6s。

对于100%的数据,$5 \times 10^8 \leq p \leq 1.1 \times 10^9$且p为质数。

题解

不对这种一不小心就会爆long long的题才是最该死的

题目要求:$\sum_{i=1}^n\sum_{j=1}^n ij\gcd(i,j)$

先化简:$\sum_{d=1}^{n}\sum_{i=1}^{n}\sum_{j=1}^{n}[\gcd(i,j)==d]ijd$

可得:$\sum_{d=1}^{n}\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}[\gcd(i,j)==1]ijd^3$

$\sum_{d=1}^{n}d^3\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}[\gcd(i,j)==1]ij$

后面的部分很莫比乌斯$\sum_{d=1}^nd^3\sum_{i=1}^{\frac{n}{d}}\mu(i)i^2(1+2+…\left\lfloor\frac{n}{id}\right\rfloor)^2$

套路啦,设$T=id$,则有$\sum_{T=1}^{n}(1+2+…\left\lfloor\frac{n}{T}\right\rfloor)\sum_{d\vert T}\mu(\frac{T}{d})(\frac{T}{d})^2d^3$

化简:$\sum_{T=1}^{n}(1+2+…\left\lfloor\frac{n}{T}\right\rfloor)T^2\sum_{d\vert T}\mu(\frac{T}{d})d$

因为$\sum_{d\vert T}\mu(\frac{T}{d})d=\phi(T)$

所以式子为$\sum_{T=1}^{n}(1+2+…\left\lfloor\frac{n}{T}\right\rfloor)T^2\phi(T)$

这样可以$O(\sqrt n)$的整除分块做了,但是数据范围觉得你太naive了

尝试用杜教筛搞出$T^2\phi(T)$,设个函数$t(i)=i^2\phi(i)$,显然这是个积性函数

设$S(n)=\sum_{i=1}^{n}t(i)$

则$f(1)S(n)=\sum_{i=1}^{n}(t*f)(i)-\sum_{i=2}^{n}f(i)S(\left\lfloor\frac{n}{i}\right\rfloor)$

$(t*f)(i)=\sum_{d\vert i}t(d)f(\frac{i}{d})=\sum_{d\vert i}\phi(d)d^2f(\frac{i}{d})$

因为$\sum_{d\vert i}\phi(d)=i$,可以设$f(i)=i^2$

所以$\sum_{d\vert i}\phi(d)d^2f(\frac{i}{d})=\sum_{d\vert i}\phi(d)d^2(\frac{i}{d})^2=i^2\sum_{d\vert i}\phi(d)=i^3$

所以$S(n)=\sum_{i=1}^{n}i^3-\sum_{i=1}^{n}i^2S(\left\lfloor\frac{n}{i}\right\rfloor)$

这个就可以杜教筛处理了

然后这题最该死的地方就是到处爆long long,mdzz我查了一晚上TAT

代码

# include<iostream>
# include<cstring>
# include<cstdio>
# include<algorithm>
# define LL long long
using namespace std;
const int MAX=5e6+1;
LL n,mod,tot,inv6,inv2;
int pm[MAX];
LL phi[MAX],ph[MAX];
bool use[MAX];
LL pow(LL b,LL a=6)
{
	LL ans=1;
	for(;b;b>>=1,a=a*a%mod)
	  if(b%2) ans=ans*a%mod;
	return ans;
}
LL SS(LL x)
{
	x%=mod;
	return x*(x+1)%mod*(x+x+1)%mod*inv6%mod;
}
LL S(LL x)
{
	x%=mod;
	return x*(x+1)%mod*inv2%mod;
}
LL dfs(LL x)
{
	if(x<MAX) return phi[x];
	LL tt=n/x,ttt;
	if(ph[tt]) return ph[tt];
	ph[tt]=S(x),ph[tt]=ph[tt]*ph[tt]%mod;
	for(LL l=2,r;l<=x;l=r+1)
	  {
	  	r=x/(x/l),ttt=(SS(r)-SS(l-1))%mod;
	  	ph[tt]=(ph[tt]-dfs(x/l)*ttt%mod)%mod;
	  }
	return ph[tt]=(ph[tt]+mod)%mod;
}
int main()
{
	scanf("%lld%lld",&mod,&n);
	phi[1]=1,inv6=pow(mod-2),inv2=pow(mod-2,2);
	for(int i=2;i<MAX;++i)
	  {
	  	if(!use[i]) pm[++tot]=i,phi[i]=i-1;
	  	for(int j=1;j<=tot&&i*pm[j]<MAX;++j)
	  	  {
	  	  	use[i*pm[j]]=1;
	  	  	if(i%pm[j]==0)
	  	  	{
	  	  		phi[i*pm[j]]=phi[i]*pm[j]%mod;
	  	  		break;
			}
			phi[i*pm[j]]=phi[i]*phi[pm[j]]%mod;
		  }
	  }
	for(LL i=1;i<MAX;++i)
	  phi[i]=(phi[i]*i%mod*i%mod+phi[i-1])%mod;
	if(n>=MAX) dfs(n);
	LL ans=0,L,R,U;
	for(LL l=1,r;l<=n;l=r+1)
	  {
	  	r=n/(n/l),U=S(n/l),L=l-1<MAX?phi[l-1]:ph[n/(l-1)],R=((r<MAX?phi[r]:ph[n/r])-L)%mod;
	  	U=U*U%mod,ans=(ans+R*U%mod)%mod;
	  }
	return printf("%lld",(ans+mod)%mod),0;
}