[洛谷3768]简单的数学题
题目链接:https://www.luogu.org/problemnew/show/P3768
看到\(\gcd\)我们就来套路一波,枚举因数可得
\[\sum\limits_{d=1}^nd^3\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor}ij[\gcd(i,j)=1]
\]
然后对最后的\(\gcd\)反演得
\[\sum\limits_{d=1}^nd^3\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{n}{d}\rfloor}ij\sum\limits_{x|i,x|j}\mu(x)
\]
然后我们更改一下枚举顺序得
\[\sum\limits_{d=1}^nd^3\sum\limits_{x=1}^{\lfloor\frac{n}{d}\rfloor}\mu(x)\sum\limits_{i=1}^{\lfloor\frac{n}{dx}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{n}{dx}\rfloor}x^2ij
\]
\[\sum\limits_{d=1}^nd^3\sum\limits_{x=1}^{\lfloor\frac{n}{d}\rfloor}x^2\mu(x)(\sum\limits_{i=1}^{\lfloor\frac{n}{dx}\rfloor}i)^2
\]
然后我们设\(h(x)=\sum\limits_{i=1}^ni\),令\(T=dx\),然后再次更改枚举顺序可得
\[\sum\limits_{T=1}^nh(\dfrac{n}{T})^2\sum\limits_{d|T}d^3×(\dfrac{T}{d})^2\mu(\dfrac{T}{d})
\]
\[\sum\limits_{T=1}^nh(\dfrac{n}{T})^2\sum\limits_{d|T}T^2d\mu(\dfrac{T}{d})
\]
\(T^2\)那东西可以提到外面,于是里面只剩下\(\sum\limits_{d|T}d\mu(\dfrac{T}{d})\),这是个卷积形式,卷积后的结果即为\(\varphi(T)\),我们设\(f(T)=T^2\varphi(T)\),那么原式变为
\[\sum\limits_{T=1}^nh(\dfrac{n}{T})^2f(T)
\]
那么我们只要求出\(f(T)\)的前缀和,我们就可以数论分块\(O(\sqrt n)\)做完这题了
然后你发现这题\(n\leqslant 10^{10}\),然后线筛肯定不行……我们需要用到杜教筛
然后我们需要找到一个优秀的\(g\),使得\(\sum\limits_{i=1}^n(f*g)(i)\)能够在\(O(1)\)的时间内算出来,根据人类智慧(其实是打表),当\(g(i)=i^2\)时,可以得到
\[\begin{aligned}(f*g)(n)&=\sum\limits_{d|n}f(d)g(\dfrac{n}{d})\\&=\sum\limits_{d|n}d^2\varphi(d)(\dfrac{n}{d})^2\\&=n^2\sum\limits_{d|n}\varphi(d)\\&=n^3\end{aligned}
\]
所以\(\sum\limits_{i=1}^n(f*g)(i)=\sum\limits_{i=1}^ni^3\),这东西的前缀和是很好算的,为\(h(n)^2\)(证明请自行Google),于是我们可以用杜教筛得到\(f(T)\)的前缀和,配合之前的式子进行一下数论分块即可
/*program from Wolfycz*/
#include<map>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define Fi first
#define Se second
#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
int x=0,f=1; char ch=gc();
for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline int read(){
int x=0,f=1; char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+ch-'0';
return x*f;
}
inline void print(int x){
if (x<0) putchar('-'),x=-x;
if (x>9) print(x/10);
putchar(x%10+'0');
}
const int N=1e7;
int prime[N+10],phi[N+10],sh[N+10];//sh(x)=\sum\limits_{i=1}^i h(i); h(x)=x^2*\varphi(x)
bool inprime[N+10];
int p,inv2,inv4,inv6;
map<ll,int>Mp;
void prepare(){
sh[1]=phi[1]=1; int tot=0;
for (int i=2;i<=N;i++){
if (!inprime[i]) prime[++tot]=i,phi[i]=i-1;
for (int j=1;j<=tot&&i*prime[j]<=N;j++){
inprime[i*prime[j]]=1;
if (i%prime[j]==0){
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
sh[i]=(sh[i-1]+1ll*i*i%p*phi[i]%p)%p;
}
}
int s2(ll n){n%=p;return 1ll*(2*n+1)*(n+1)%p*n%p*inv6%p;}
int SH(ll n){
if (n<=N) return sh[n];
map<ll,int>::iterator it=Mp.find(n);
if (it!=Mp.end()) return it->Se;
int tmp=n%p,res=1ll*tmp*tmp%p*(tmp+1)%p*(tmp+1)%p*inv4%p;
for (ll i=2,pos;i<=n;i=pos+1){
pos=n/(n/i);
res=(res-1ll*(s2(pos)-s2(i-1))*SH(n/i)%p)%p;
}
res=(res+p)%p;
Mp.insert(map<ll,int>::value_type(n,res));
return res;
}
int s1(ll n){n%=p;return 1ll*n*(n+1)%p*inv2%p;}
int mlt(int a,int b){
int res=1;
for (;b;b>>=1,a=1ll*a*a%p) if (b&1) res=1ll*res*a%p;
return res;
}
int main(){
ll n;
scanf("%d%lld",&p,&n);
inv2=mlt(2,p-2);
inv4=mlt(4,p-2);
inv6=mlt(6,p-2);
prepare(); int Ans=0;
for (ll i=1,pos;i<=n;i=pos+1){
pos=n/(n/i);
Ans=(Ans+1ll*(SH(pos)-SH(i-1))*s1(n/i)%p*s1(n/i)%p)%p;
}
printf("%d\n",(Ans+p)%p);
return 0;
}