SP26108 Trending GCD
Luogu 链接
SPOJ 链接
Virtual Judge 链接
题意
题目描述
已知 \(n\) 和 \(m\)(\(1\le n,m\le10^6\)),求
\[\sum_{i=1}^n\sum_{j=1}^mij\times\gcd(i,j)\times\mu^2(\gcd(i,j)) \]由于答案可能非常大,你只需输出其对 \(10^9+7\) 取模取模后的结果。
输入格式
多测,第一行一个正整数 \(T\)(\(T\le10^3\)),代表组数。
对于每组数据,一行两个正整数 \(n\) 和 \(m\),含意见题目描述。
输出格式
见题目描述。
思路
不妨设 \(n\le m\),则有:
\[\begin{aligned}
&\sum_{i=1}^n\sum_{j=1}^mij\times\gcd(i,j)\times\mu^2(\gcd(i,j))\\
=&\sum_{d=1}^nd^3\mu^2(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}ij[\gcd(i,j)=1]\\
=&\sum_{d=1}^nd^3\mu^2(d)\sum_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{d}\rfloor}ij\sum_{k\mid i,k\mid j}\mu(k)\\
=&\sum_{d=1}^nd^3\mu^2(d)\sum_{t=1}^{\lfloor\frac{n}{d}\rfloor}t^2\mu(t)\sum_{i=1}^{\lfloor\frac{n}{td}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{td}\rfloor}ij\\
=&\sum_{T=1}^nT^2\sum_{d\mid T}d\mu^2(d)\mu(\dfrac{T}{d})\sum_{i=1}^{\lfloor\frac{n}{T}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{T}\rfloor}ij\\
=&\sum_{T=1}^nT^2S(\lfloor\dfrac{n}{T}\rfloor)S(\lfloor\dfrac{m}{T}\rfloor)\sum_{d\mid T}d\mu^2(d)\mu(\dfrac{T}{d})\\
=&\sum_{T=1}^nT^2f(T)S(\lfloor\dfrac{n}{T}\rfloor)S(\lfloor\dfrac{m}{T}\rfloor)
\end{aligned}\]
其中 \(S(n)=\displaystyle\sum_{i=1}^ni=\dfrac{n(n+1)}{2},f(n)=\displaystyle\sum_{d\mid n}d\mu^2(d)\mu(\dfrac{n}{d})\)。
先预处理用线性筛筛出 \(f(n)\),并处理出 \(n^2f(n)\) 的前缀和,再用数论分块求解即可。
至于怎么用线性筛筛像 \(f(n)\) 这种一般的积性函数,请看我的这篇博客。
记得取模。
程序
#include<cstdlib>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#include<cstdio>
#include<iostream>
#include<vector>
#include<map>
#include<cmath>
#include<iomanip>
#include<string>
#include<stack>
#define ll long long
#define ull unsigned long long
#define ld long double
#define INF 0x3f3f3f3f
#define ls rt<<1
#define rs rt<<1|1
#define lb(x) ((x)&(-(x)))
#define pb push_back
using namespace std;
const ll N=1e6+10,mod=1e9+7;
//#define use_file
#define more_test
#define need_init
#ifdef more_test
int T;
#endif
ll cnt,P[N],f[N],g[N];bool np[N];
void init(ll n=N-10){
cnt=0;
np[0]=np[1]=true;
f[1]=g[1]=1;
for(ll x_=2;x_<=n;++x_){
if(!np[x_]){
++cnt;
P[cnt]=x_;
f[x_]=x_-1;
g[x_]=x_;
}
for(ll i=1;i<=cnt&&P[i]*x_<=n;++i){
ll x=P[i]*x_;
np[x]=true;
if(x_%P[i]==0){
g[x]=g[x_]*P[i];
if(g[x]==x){
if(g[x]==P[i]*P[i])f[x]=-P[i];
else f[x]=0;
}
else f[x]=f[g[x]]*f[x/g[x]];
break;
}
g[x]=P[i],f[x]=f[P[i]]*f[x_];
}
}
for(ll x=1;x<=n;++x)f[x]=((f[x-1]+x*x%mod*f[x]%mod)%mod+mod)%mod;
}
ll S(ll x){return x*(x+1)/2%mod;}
ll n,m;
ll ans;
void SOLVE(/*int test_id*/){
scanf("%lld%lld",&n,&m);
ans=0;
if(n>m)swap(n,m);
for(ll l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans=(ans+((f[r]-f[l-1]+mod)%mod*((S(n/l)*S(m/l))%mod)%mod)%mod)%mod;
}
printf("%lld\n",ans);
}
/*
Input:
Output:
*/
int main(){
#ifdef use_file
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
#endif
#ifdef need_init
init();
#endif
#ifdef more_test
scanf("%d",&T);
for(int i=1;i<=T;++i)SOLVE(/*i*/);
#else
SOLVE();
#endif
return 0;
}

浙公网安备 33010602011771号