私のアプローチは2つの式に基づいています。
\ [[N- = 1] = \ sum_ {D | N-}。\ MU(D)\]
\ [\ sigma_0(Iは、Jを*)= \ sum_ {X | I} \ sum_ {Y | J} [GCD(X 、Y)= 1] \]
前記\(\ sigma_0は、(N)\ ) を表し\(\ N-)数の除数
最初の式は、メビウスの基本的な特性の関数である、第二の式で示されるように、考えることができる\(iはj個の\を*)の素因数のそれぞれにおける(\ sigma_0(iはjは* \ \)) 寄与品質係数のための\(P \) 、それであれば\(私は\)の範囲内の数\(K_1 \)、それ\(J \)の範囲内の数\(K_2 \)次いで、(\ \ sigma_0(I * J)\ ) で\(P \)寄与\((K_1 + + K_2。1)\) ()式のいくつかの数について、で\(GCD(X、Y) = 1 \)のいずれかの場合には\(X \)で\(P \)番号0であるか、または\(Y \)で\(P \)数は、合計0である((K_1 + K_2 + 1 \ )\)プログラムの種類、および\(私はjは\)*式は左右に等しくなるように、同じ貢献を。
次に、あなたが快適な表現にそれをプッシュすることができます!
\ [\ sum_ {i = 1} ^ {N} \ sum_ {J = 1} ^ {M} \ sigma_0(iはjは*)\]
\ [\ sum_ {i = 1} ^ {N} \ sum_ {J = 1} ^ {M} \ sum_ {X | I} \ sum_ {Y | J} [GCD(X、Y)= 1] \]
\ [\ sum_ {X = 1} ^ {N} \ sum_ {Y = 1} ^ m個の\ sum_ {i = 1} ^ {\ lfloorの\のFRAC {n}は{X} \ rfloor} \ sum_ {J = 1 } ^ {\ lfloorの\のFRAC {M} {Y} \ rfloor} [GCD(X、Y)= 1] \]
\ [\ sum_ {X = 1} ^ {N} \ sum_ {Y = 1} ^ M \ lfloor \ FRAC {n}は{X} \ rfloor \ lfloor \ FRAC {M} {Y} \ rfloor \ sum_ {K | GCD(X、Y)} \ミュー(K)\]
\ [\ sum_ {k = 1} ^ {N} \ sum_ {X = 1} ^ {\ lfloorの\のFRAC {N} {K} \ rfloor} \ sum_ {Y = 1} ^ {\ lfloorの\のFRAC {M } {K} \ rfloor} \ lfloor \ FRAC {N} {KX} \ rfloor \ lfloor \ FRAC {M} {KY} \ rfloorミュー\(K)\]
\ [\ sum_ {k = 1} ^ {n}はミュー(K)(\ sum_ {X = 1} ^ {\ lfloorの\のFRAC {N} {K} \ rfloor} \ lfloor \ FRAC {N} {KX \ } \ rfloor)(\ sum_ {Y = 1} ^ {\ lfloorの\のFRAC {M} {K} \ rfloor} \ lfloor \ FRAC {M} {KY} \ rfloor)\]
その後、我々は設定\(S(N)= \ sum_ {I = 1} ^ {N-} \ lfloor \ FRAC {N-} {I} \ rfloor \) 、明らかに\(S(n)が\)されているO(\を(\ SQRT {N})\ ) 計算
そして、上記の式を変換することができます。
\ [\ sum_ {k = 1} ^ {n}はミュー(K)S(\ \ lfloorの\のFRAC {N} {K} \ rfloor)S({\ lfloorの\のFRAC {M} {K} \ rfloor}) \]
まず、前処理\(S(1)-S(MAXN)\) 、そして、あなたがすることができます\(O(\ sqrtの{N })\) に答えるために、各お問い合わせに!
コード:
#include<bits/stdc++.h>
using namespace std;
#define N 50007
#define ll long long
const int lim=50000;
ll s[N];
int ui[N],pr[N],cnt;
bool zhi[N];
void Init()
{
int i,j;
ui[1]=1;
for(i=2;i<=lim;i++)
{
if(!zhi[i])
{
pr[++cnt]=i;
ui[i]=-1;
}
for(j=1;j<=cnt&&i*pr[j]<=lim;j++)
{
int p=pr[j],x=i*p;
zhi[x]=true;
if(i%p==0)
{
ui[x]=0;
break;
}
ui[x]=-ui[i];
}
}
for(i=1;i<=lim;i++)
ui[i]+=ui[i-1];
for(i=1;i<=lim;i++)
{
int l,r;
for(l=1;l<=i;l=r+1)
{
r=i/(i/l);
s[i]+=1ll*(r-l+1)*(i/l);
}
}
}
int main()
{
int n,m,t;
Init();
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
int l1=1,r1,l2=1,r2,cur=1;
ll ans=0;
while(l1<=n&&l2<=m)
{
int l,r;
r1=n/(n/l1),r2=m/(m/l2);
l=cur;
if(r1<r2)r=r1,cur=l1=r1+1;
else r=r2,cur=l2=r2+1;
ans+=1ll*(ui[r]-ui[l-1])*s[n/l]*s[m/l];
}
printf("%lld\n",ans);
}
return 0;
}