BZOJ P2301 [HAOI2011] Problem b【莫比乌斯】

f(n,m)=ni=1mj=1(gcd(i,j)==k) f ( n , m ) = ∑ i = 1 n ∑ j = 1 m ( g c d ( i , j ) == k )

=nki=1mkj=1(gcd(i,j)==1) = ∑ i = 1 n k ∑ j = 1 m k ( g c d ( i , j ) == 1 )

=nki=1mkj=1d|i,d|jμ(d) = ∑ i = 1 n k ∑ j = 1 m k ∑ d | i , d | j μ ( d )

=d|i,d|jμ(d)nki=1mkj=1 = ∑ d | i , d | j μ ( d ) ∑ i = 1 n k ∑ j = 1 m k

=min(nk,mk)d=1μ(d)ndki=1mdkj=1 = ∑ d = 1 m i n ( n k , m k ) μ ( d ) ∑ i = 1 n d k ∑ j = 1 m d k

=min(nk,mk)d=1μ(d)ndkmdk = ∑ d = 1 m i n ( n k , m k ) μ ( d ) ⌊ n d k ⌋ ∗ ⌊ m d k ⌋

Ans=f(b,d)+f(a1,c1)f(a1,b)f(b,c1) A n s = f ( b , d ) + f ( a − 1 , c − 1 ) − f ( a − 1 , b ) − f ( b , c − 1 )

由于直接计算 f f 时间复杂度仍然高,但是结合 μ(d) μ ( d ) 的性质我们发现其实可以对 μ(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;
}

你可能感兴趣的:(BZOJ,数学-莫比乌斯)