BZOJ 2301 [HAOI2011]Problem b 【莫比乌斯反演】

Description 

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

HINT

  1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000

Solution

题意:如描述

题目和 BZOJ 1101 很像,只有 x , y 的取值范围又增加了一些限制

现在我们已经会求任意1<=x<=a,1<=y<=b,满足gcd( x,y ) = d 的(x,y)对数,设为 calc ( a,b )

于是用容斥推一下

答案应该是 calc( b,d ) - calc( a,d ) - calc( b,c ) + calc( a,c )

  1 #include<map>
  2 #include<cmath>
  3 #include<ctime>
  4 #include<queue>
  5 #include<stack>
  6 #include<cstdio>
  7 #include<climits>
  8 #include<iomanip>
  9 #include<cstring>
 10 #include<cstdlib>
 11 #include<iostream>
 12 #include<algorithm>
 13 
 14 #define maxp 50000
 15 #define maxn 50000+5
 16 #define set(a,b) memset(a,(b),sizeof(a))
 17 #define fr(i,a,b) for(ll i=(a),_end_=(b);i<=_end_;i++)
 18 #define rf(i,b,a) for(ll i=(a),_end_=(b);i>=_end_;i--)
 19 #define fe(i,a,b) for(int i=first[(b)],_end_=(a);i!=_end_;i=s[i].next)
 20 #define fec(i,a,b) for(int &i=cur[(b)],_end_=(a);i!=_end_;i=s[i].next)
 21 
 22 using namespace std;
 23 
 24 typedef long long ll;
 25 
 26 int prime[maxn],pri[maxn],tot=0;
 27 int sum[maxn],miu[maxn];
 28 int ans;
 29 int n,m;
 30 
 31 void read()
 32 {
 33 #ifndef ONLINE_JUDGE
 34   freopen("2301.in","r",stdin);
 35   freopen("2301.out","w",stdout);
 36 #endif
 37   //cin >> n ;
 38   scanf("%d",&n);
 39 }
 40 
 41 void write()
 42 {}
 43 
 44 void print()
 45 {
 46   //cout << ans << endl ;
 47   printf("%d\n",ans);
 48 }
 49 
 50 void mobius()
 51 {
 52   miu[1]=1;
 53   fr(i,2,maxp){
 54     if( !prime[i] ) pri[++tot]=i,miu[i]=-1;
 55     int j=1;
 56     while( j<=tot && pri[j]*i<=maxp ){
 57       prime[pri[j]*i]=1;
 58       if( i%pri[j]==0 ){
 59     miu[pri[j]*i]=0;
 60     break;
 61       }
 62       miu[pri[j]*i]=-miu[i];
 63       j++;
 64     }
 65   }
 66   fr(i,1,maxp)
 67     sum[i]=sum[i-1]+miu[i];
 68 }
 69 
 70 int calc(int x,int y)
 71 {
 72   int res=0,pos,i=1;
 73   if(x>y) swap(x,y);
 74   while(i<=x){
 75     pos=min(x/(x/i),y/(y/i));
 76     res+=(sum[pos]-sum[i-1])*(x/i)*(y/i);
 77     i=pos+1;
 78   }
 79   return res;
 80 }
 81 
 82 void work()
 83 {
 84   mobius();
 85   fr(i,1,n){
 86     int a,b,c,d,k;
 87     //cin >> a >> b >> d ;
 88     scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
 89     ans=calc((a-1)/k,(c-1)/k)+calc(b/k,d/k)-calc((a-1)/k,d/k)-calc(b/k,(c-1)/k);
 90     print();
 91   }
 92 }
 93 
 94 int main()
 95 {
 96   read();
 97   work();
 98   write();
 99   return 0;
100 }

 

posted @ 2015-07-01 13:37  ST_Saint  阅读(119)  评论(0编辑  收藏  举报