bzoj 2301 [HAOI2011]Problem b (莫比烏斯反演)

Description

對於給出的n個詢問,每次求有多少個數對(x,y),滿足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函數爲x和y的最大公約數。



Input

第一行一個整數n,接下來n行每行五個整數,分別表示a、b、c、d、k

 

Output

共n行,每行一個整數表示滿足要求的數對(x,y)的個數

 

Sample Input

2

2 5 1 5 1

1 5 1 5 2



Sample Output


14

3



HINT



100%的數據滿足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000


題意:給定兩個數x,y,   a <= x <= b, c <= y <= d,讓你求有多少對gcd(x,y) == k。gcd(x,y) 和 gcd(y,x)算兩對。

我們前面做過求 [1,b] 區間與 [1,d] 區間的 gcd(x,y) == k的題(如果沒做過,請點擊這裏)。

我們先令:

a = (a-1)/k;
b = b/k;
c = (c-1)/k;
d = d/k;

這題我們可以先求出[1,b] 與 [1,d]的答案,但是這裏會有重複,因爲[1,a] 和 [1,c]區間都不在範圍內,這裏面就多算了 [1,a] 與 [1,c] 、[1,a]與[1,d] 、 [1,c]與[1,b],

所以最後的答案就是  solve(b,d) - solve(a,d) - solve(c,b) + solve(a,c); (因爲[1,a] 與 [1,c] 這個區間被減了兩次,所以加上一次)


而且這題數據組數很多,所以得分塊處理,對於一個i,到min(b/(b/i),d/(d/i))這一段的值都是一樣的,所以一起加到答案上就行了,提前處理一下莫比烏斯函數的前綴和。


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;

const int maxn = 1e5 + 10;
int p[maxn/10];
int flag[maxn];
int mu[maxn];
int cnt = 0;
int sum[maxn];

void init()
{
    int i,j;
    mu[1] = 1;
    for(i=2;i<maxn;i++)
    {
        if(!flag[i])
        {
            p[cnt++] = i;
            mu[i] = -1;
        }
        for(j=0;j<cnt&&p[j]*i<maxn;j++)
        {
            flag[p[j]*i] = 1;
            if(i % p[j] == 0)
            {
                mu[p[j]*i] = 0;
                break;
            }
            mu[p[j]*i] = -mu[i];
        }

    }
    for(i=1;i<maxn;i++)
        sum[i] = sum[i-1] + mu[i];
}

LL solve(int b,int d)
{
    LL ans = 0;
    for(int i=1,last = 0;i<=min(b,d);i=last+1)
    {
        last = min(b/(b/i),d/(d/i));
        ans += (LL)(b/i)*(d/i)*(sum[last]-sum[i-1]);
    }
    return ans;
}
int main(void)
{
    int T,a,b,c,d,k,i,j;
    init();
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
        a = (a-1)/k;
        b = b/k;
        c = (c-1)/k;
        d = d/k;
        LL ans = solve(b,d) - solve(a,d) - solve(c,b) + solve(a,c);
        printf("%lld\n",ans);
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章