[莫比乌斯反演][整除分块] Bzoj P2301 Problem b

题目描述

对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。

 

题解

  •  

 

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #define N 60010
 4 #define ll long long
 5 using namespace std;
 6 ll n,k,mobius[N],p[N],bz[N],s[N];
 7 void read(ll &x)
 8 {
 9     x=0; ll p=1;
10     static char c;c=getchar();
11     while (!isdigit(c)){if(c=='-')p=-1;c=getchar();}
12     while (isdigit(c)) {x=(x<<1)+(x<<3)+(c-48);c=getchar();}
13     x*=p;   
14 }
15 ll calc(ll x,ll y)
16 {
17     ll r=min(x,y),ans=0;
18     for (ll a=1,b;a<=r;a=b+1) b=min(x/(x/a),y/(y/a)),ans+=((x/(a*k))*(y/(a*k))*(s[b]-s[a-1]));
19     return ans;
20 }
21 int main()
22 {
23     read(n),mobius[1]=1;
24     for (ll i=2;i<=N;i++)
25     {
26         if (!bz[i]) mobius[i]=-1,p[++p[0]]=i;
27         for (ll j=1;j<=p[0]&&i*p[j]<=N;j++)
28         {
29             bz[i*p[j]]=1;
30             if (i%p[j]==0) break; else mobius[i*p[j]]=-mobius[i];
31         }
32     }
33     for (ll i=1;i<=N;i++) s[i]=s[i-1]+mobius[i];
34     for (ll a,b,c,d,k,l,r,sum;n;n--)
35     {
36         read(a),read(b),read(c),read(d),read(k);
37         a=(a-1)/k,b=b/k,c=(c-1)/k,d=d/k,l=1,sum=0;
38         if (a>c) swap(a,c),swap(b,d);
39         for (ll A,B,C,D;l<=a;l=r+1) A=a/(a/l),B=b/(b/l),C=c/(c/l),D=d/(d/l),r=min(A,min(B,min(C,D))),sum+=(s[r]-s[l-1])*(b/l-a/l)*(d/l-c/l);
40         for (ll A,B,C,D;l<=min(b,c);l=r+1) B=b/(b/l),C=c/(c/l),D=d/(d/l),r=min(B,min(C,D)),sum+=(s[r]-s[l-1])*(b/l)*(d/l-c/l);
41         for (ll A,B,C,D;l<=min(b,d);l=r+1) B=b/(b/l),D=d/(d/l),r=min(B,D),sum+=(s[r]-s[l-1])*(b/l)*(d/l);
42         printf("%lld\n",sum);
43     }
44 }

 

posted @ 2019-08-08 15:09  BEYang_Z  阅读(...)  评论(...编辑  收藏