【BZOI 3994] [SDOI2015]数と数の約
フェイス質問
集合D(x)は、Nは、Mは、尋ねる所与除数Xの数であり、\(\和_ {i = 1} ^ n個の\ sum_ {i = 1} ^ MD(iは時間j)を\ \)
Tグループは、尋ねた\(N、M、T \のLeq 50000 \)
分析
まず、結論があります
\ [D(NM)= \和_ {I | N} \和_ {J | M} [GCD(I、J)= 1] \]
約ナノメートルの数として表すことができるからである(iは時間を\ \ FRAC {M \} {J} \) の形態と、カウントを繰り返すことを確実にしないために、\(GCD(i、j)を = 1 \)
したがって、我々は、式をプッシュし始めることができます
\ [ANS = \ sum_ {P = 1} ^ n個の\ sum_ {Q = 1} ^ m個の\ sum_ {I | P} \和_ {J | Q} [GCD(I、J)= 1] \]
注目の各\((i、j)は\ ) 有するP、Q、それらが生成する複数の\(\ lfloorの\のFRAC {N } {I} \ rfloor回\ \ lfloor FRAC \ {M} {J} \ rfloor \)の貢献
\ [= \ sum_ {i = 1} ^ n個の\ sum_ {J = 1} ^ M [GCD(I、J)= 1] \ lfloor \ FRAC {n}は{I} \ rfloor \ lfloor \ FRAC {M} {J} \ rfloor \]
\ [= \ sum_ {i = 1} ^ n個の\ sum_ {J = 1} ^ m個の\ varepsilon(GCD(I、J))\ lfloor \ FRAC {n}は{I} \ rfloor \ lfloor \ FRAC {M} {J} \ rfloor \]
\(\ varepsilon(N)= \ sum_ {D | n}はミュー(D)\ \)
\ [= \ sum_ {i = 1} ^ n個の\ sum_ {J = 1} ^ M \ lfloor \ FRAC {n}は{I} \ rfloor \ lfloor \ FRAC {M} {J} \ rfloor \ sum_ {D | GCDミュー\(i、j)は}(D)\]
場合は、明らかに、和の順序、最初の列挙dを変更| \(GCD(I、J)\ D) 、その後、\(J \ | | dをI、D) 、
D iが直接J dは、複数のDV(交換、複数デュを交換+、デュ\ n型のLeq、DV \のLeq Mが\)で\(U、V \ N ^を)
\ [= \ sum_ {D = 1} ^ {分(N、M)}ミュー(D)\ \ sum_ {U = 1} ^ {\ lfloor N / Dの\ rfloor} \ sum_ {V = 1} ^ { \ lfloorのM / Dの\のrfloor} \ lfloor \ FRAC {N} {デュ} \ rfloor \ lfloor \ FRAC {M} {DV} \ rfloor \]
\ [= \ sum_ {D = 1} ^ {分(N、M)}ミュー(D)\ \ sum_ {U = 1} ^ {\ lfloor N / Dの\ rfloor} \ sum_ {V = 1} ^ { \ lfloorのM / Dの\のrfloor} \ lfloor \ FRAC {\ lfloor N / Dの\ rfloor} {U} \ rfloor \ lfloor \ FRAC {\ lfloor M / Dの\のrfloor} {V} \ rfloor \]
\ [= \ sum_ {D = 1} ^ {分(N、M)}ミュー(D)\ \ sum_ {U = 1} ^ {\ lfloor N / Dの\ rfloor} \ lfloor \ FRAC {\ lfloor N / D \ rfloor} {U} \ rfloor \ sum_ {V = 1} ^ {\ lfloorのM / Dの\のrfloor} \ lfloor \ FRAC {\ lfloorのM / Dの\のrfloor} {V} \ rfloor \]
令\(G(N)= \和_ {D = 1} ^ N \ lfloor \ FRAC {n}は{D} \ rfloor \)
\ [= \ sum_ {D = 1} ^ {分(N、M)}ミュー(D)G(\ lfloorの\のFRAC {n}が{D} \ rfloor)G(\ lfloorの\のFRAC {M} {D \ } \ rfloor)\]
迅速に評価する方法を検討してください。単一\(G(N)\)で数論ブロックを使用してもよい(O(\ SQRT N)\ )\ 時間で決定された、合計時間複雑度\(O(N \ SQRT N-)\) 。次に、線形篩\(\ MU \) 、寸法\(\ムー、G \)プレフィックスと
D列挙法の数により各質問には、総時間の複雑ブロックすることができる\(Oを(N \ SQRT N + T \ SQRT N)\)
コード
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 50000
using namespace std;
typedef long long ll;
int t;
int n,m;
int cnt;
bool vis[maxn+5];
int prime[maxn+5];
int mu[maxn+5];
ll sum_mu[maxn+5];
int g[maxn+5];
void sieve(int n){
mu[1]=1;
for(int i=2;i<=n;i++){
if(!vis[i]){
prime[++cnt]=i;
mu[i]=-1;
}
for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
vis[i*prime[j]]=1;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}else{
mu[i*prime[j]]=-mu[i];
}
}
}
for(int i=1;i<=n;i++) sum_mu[i]=sum_mu[i-1]+mu[i];
for(int i=1;i<=n;i++){
int l,r;
for(l=1;l<=i;l=r+1){
r=i/(i/l);
g[i]+=(ll)(r-l+1)*(i/l);
}
}
}
ll calc(int n,int m){
int l,r;
if(n<m) swap(n,m);
ll ans=0;
for(l=1;l<=m;l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=(sum_mu[r]-sum_mu[l-1])*g[n/l]*g[m/l];
}
return ans;
}
int main(){
sieve(maxn);
scanf("%d",&t);
while(t--){
scanf("%d %d",&n,&m);
printf("%lld\n",calc(n,m));
}
}