bzoj2301 [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

 

正解:莫比乌斯函数。

莫比乌斯函数板子题。。我能说我是为了刷题量才做这题的吗。。

易知$Ans=\sum_{i=1}^{b}\sum_{j=1}^{d}[\gcd(i,j)==k]-\sum_{i=1}^{a-1}\sum_{j=1}^{d}[\gcd(i,j)==k]-\sum_{i=1}^{b}\sum_{j=1}^{c-1}[\gcd(i,j)==k]+\sum_{i=1}^{a-1}\sum_{j=1}^{b-1}[\gcd(i,j)==k]$

于是变成最裸的莫比乌斯函数推导。同除以k,然后把$\mu(p)$的枚举提前,各种套路。。

最后是$Ans=\sum_{p=1}^{min(\frac{b}{k},\frac{d}{k})}\mu(p)\left \lfloor \frac{b}{kp} \right \rfloor\left \lfloor \frac{d}{kp} \right \rfloor-\sum_{p=1}^{min(\frac{a-1}{k},\frac{d}{k})}\mu(p)\left \lfloor \frac{a-1}{kp} \right \rfloor\left \lfloor \frac{d}{kp} \right \rfloor-\sum_{p=1}^{min(\frac{b}{k},\frac{c-1}{k})}\mu(p)\left \lfloor \frac{b}{kp} \right \rfloor\left \lfloor \frac{c-1}{kp} \right \rfloor
\sum_{p=1}^{min(\frac{a-1}{k},\frac{c-1}{k})}\mu(p)\left \lfloor \frac{a-1}{kp} \right \rfloor\left \lfloor \frac{c-1}{kp} \right \rfloor$

然后数论分块,这道题就做完了。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <complex>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define N (50010)
16 #define il inline
17 #define RG register
18 #define ll long long
19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
20 
21 using namespace std;
22 
23 int vis[N],mu[N],prime[N],n,m,a,b,c,d,k,cnt,pos;
24 ll ans;
25 
26 il int gi(){
27     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
28     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
29 }
30 
31 il void sieve(){
32     vis[1]=mu[1]=1;
33     for (RG int i=2;i<N;++i){
34     if (!vis[i]) vis[i]=1,mu[i]=-1,prime[++cnt]=i;
35     for (RG int j=1,k=i*prime[j];j<=cnt && k<N;++j,k=i*prime[j]){
36         vis[k]=1; if (i%prime[j]) mu[k]=-mu[i]; else break;
37     }
38     }
39     for (RG int i=1;i<N;++i) mu[i]+=mu[i-1]; return;
40 }
41 
42 il void work(){
43     a=gi(),b=gi(),c=gi(),d=gi(),k=gi();
44     n=b/k,m=d/k,pos=0,ans=0; if (n>m) swap(n,m);
45     for (RG int i=1;i<=n;i=pos+1){
46     pos=min(n/(n/i),m/(m/i));
47     ans+=(ll)(mu[pos]-mu[i-1])*(ll)(n/i)*(ll)(m/i);
48     }
49     n=(a-1)/k,m=d/k,pos=0; if (n>m) swap(n,m);
50     for (RG int i=1;i<=n;i=pos+1){
51     pos=min(n/(n/i),m/(m/i));
52     ans-=(ll)(mu[pos]-mu[i-1])*(ll)(n/i)*(ll)(m/i);
53     }
54     n=b/k,m=(c-1)/k,pos=0; if (n>m) swap(n,m);
55     for (RG int i=1;i<=n;i=pos+1){
56     pos=min(n/(n/i),m/(m/i));
57     ans-=(ll)(mu[pos]-mu[i-1])*(ll)(n/i)*(ll)(m/i);
58     }
59     n=(a-1)/k,m=(c-1)/k,pos=0; if (n>m) swap(n,m);
60     for (RG int i=1;i<=n;i=pos+1){
61     pos=min(n/(n/i),m/(m/i));
62     ans+=(ll)(mu[pos]-mu[i-1])*(ll)(n/i)*(ll)(m/i);
63     }
64     printf("%lld\n",ans); return;
65 }
66 
67 int main(){
68     File("b");
69     sieve();
70     RG int T=gi();
71     while (T--) work();
72     return 0;
73 }

 

posted @ 2017-03-16 10:18  wfj_2048  阅读(152)  评论(0编辑  收藏  举报