[SDOI2015]约数个数和
题意:(d(x))为(x)的约数个数,求(sum_{i=1}^nsum{j=1}^md(ij))
由结论得$$ans=sum_{i=1}nsum_{j=1}msum_{x|i}sum_{y|j}[GCD(x,y)1]$$
我们换个方向,考虑(x, y)的贡献,则 $$ans=sum_{x=1}nsum_{y=1}mlfloorfrac{n}{x}
floorlfloorfrac{m}{y}
floor[GCD(x, y)1]$$
令$$f(d)=sum_{x=1}nsum_{y=1}mlfloorfrac{n}{x}
floorlfloorfrac{m}{y}
floor[GCD(x, y)==d]$$
[g(d)=sum_{d|n}f(d)
]
[=sum_{x=1}^nsum_{y=1}^mlfloorfrac{n}{x}
floorlfloorfrac{m}{y}
floor[d|GCD(x, y)]
]
[=sum_{x=1}^{lfloorfrac{n}{d}
floor}sum_{y=1}^{lfloorfrac{m}{d}
floor}lfloorfrac{n}{xd}
floorlfloorfrac{m}{yd}
floor
]
[=(sum_{x=1}^{lfloorfrac{n}{d}
floor}lfloorfrac{n}{xd}
floor)(sum_{y=1}^{lfloorfrac{m}{d}
floor}lfloorfrac{m}{yd}
floor)
]
[f(d)=sum_{d|n}mu(frac{n}{d})g(n)
]
则(ans=f(1)=sum_{d=1}^nmu(d)g(d))
令(sum(n)=sum_{i=1}^nlfloorfrac{n}{i}
floor)
则(ans=sum_{d=1}^nmu(d)*sum(lfloorfrac{n}{d}
floor)*sum(lfloorfrac{m}{d}
floor))
不开(O_2)会(T)掉两个点
void init(){
miu[1]=1;
for(int i=2; i < Maxn; i++){
if(!p[i]) p[++ptot]=i, miu[i]=-1;
for(int j=1, x; j <= ptot && (x=i*p[j]) < Maxn; j++){
p[x]=1; if(i%p[j] == 0) break; miu[x]=-miu[i];
}
}
for(int i=1; i < Maxn; i++) for(int l=1, r=0; r < i; l=r+1)
r=i/(i/l), sum[i]+=1ll*(r-l+1)*(i/l);
for(int i=1; i < Maxn; i++) miu[i]+=miu[i-1];
}
void solve(){
int T=read(); init();
while(T--){
ll n=read(), m=read(), ans=0; if(n > m) swap(n, m);
for(int l=1, r=0; r < n; l=r+1){
r=min(n/(n/l), m/(m/l));
ans+=(miu[r]-miu[l-1])*sum[n/l]*sum[m/l];
}
printf("%lld
", ans);
}
}