# 莫（meng）比（bi）乌斯反演--BZOJ2301: [HAOI2011]Problem b

n<=50000个询问，每次问a<=x<=b，c<=y<=d中有多少gcd(x,y)=K的(x,y)。a,b,c,d,K<=50000。

 1 #include<cstring>
2 #include<cstdlib>
3 #include<cstdio>
4 //#include<assert.h>
5 #include<algorithm>
6 //#include<iostream>
7 using namespace std;
8
9 int a,b,c,d,K,T;
10
11 #define maxn 50011
12 int miu[maxn],prime[maxn],lp=0,summiu[maxn]; bool notprime[maxn];
13 void pre(int n=50001)
14 {
15     miu[1]=summiu[1]=1;
16     for (int i=2;i<=n;i++)
17     {
18         if (!notprime[i]) {prime[++lp]=i; miu[i]=-1;}
19         summiu[i]=summiu[i-1]+miu[i];
20         for (int j=1;j<=lp && 1ll*i*prime[j]<=n;j++)
21         {
22             notprime[i*prime[j]]=1;
23             if (i%prime[j]) miu[i*prime[j]]=-miu[i];
24             else {miu[i*prime[j]]=0; break;}
25         }
26     }
27 }
28
29 #define LL long long
30 LL solve(int p,int q)
31 {
32     LL ans=0;
33     for (int i=1,last,to=min(p,q);i<=to;i=last+1)
34     {
35         last=min(p/(p/i),q/(q/i));
36         ans+=1ll*(p/i)*(q/i)*(summiu[last]-summiu[i-1]);
37     }
38     return ans;
39 }
40
41 int main()
42 {
43     pre();
44     scanf("%d",&T);
45 while (T--)
46 {
47     scanf("%d%d%d%d%d",&a,&b,&c,&d,&K);
48     printf("%lld\n",solve(b/K,d/K)-solve((a-1)/K,d/K)-solve(b/K,(c-1)/K)+solve((a-1)/K,(c-1)/K));
49 }
50     return 0;
51 }
View Code

posted @ 2017-12-31 15:46  Blue233333  阅读(...)  评论(...编辑  收藏