f(n,m)=∑ni=1∑mj=1(gcd(i,j)==k)
=∑nki=1∑mkj=1(gcd(i,j)==1)
=∑nki=1∑mkj=1∑d|i,d|jμ(d)
=∑d|i,d|jμ(d)∑nki=1∑mkj=1
=∑min(nk,mk)d=1μ(d)∑ndki=1∑mdkj=1
=∑min(nk,mk)d=1μ(d)⌊ndk⌋∗⌊mdk⌋
Ans=f(b,d)+f(a−1,c−1)−f(a−1,b)−f(b,c−1)
由于直接计算
f
时间复杂度仍然高,但是结合
μ(d)
的性质我们发现其实可以对
μ(d)
做一个前缀和优化一下。
void Mobius(){
......
}
LL GetAns(LL N,LL M,LL K){
LL I,Ans=0,Last;
N/=K,M/=K;
if(N>M){
swap(N,M);
}
for(I=1;I<=N;I=Last+1){
Last=min(N/(N/I),M/(M/I));
Ans+=(Miu[J]-Miu[I-1])*(N/I)*(M/I);
}
return Ans;
}
int main(){
LL I,J,K;
N=Read();Mobius();
for(I=1;I<=N;I++){
A=Read(),B=Read(),C=Read(),D=Read(),K=Read();
Ans=GetAns(B,D,K)-GetAns(A-1,D,K)-GetAns(B,C-1,K)+GetAns(A-1,C-1,K);
......
}
return 0;
}