码迷,mamicode.com
首页 > 其他好文 > 详细

[HAOI2011]Problem b 题解

时间:2017-01-20 16:23:48      阅读:221      评论:0      收藏:0      [点我收藏+]

标签:void   min   space   ++i   return   color   namespace   while   lag   

题目大意:

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

思路:

  设f(k)为当1≤x≤n,1≤y≤m,且n≤m,使gcd(x,y)=k的数对(x,y)的对数,g(k)为当1≤x≤n,1≤y≤m,且n≤m,使k|gcd(x,y)的数对(x,y)的对数。技术分享,莫比乌斯反演,得技术分享技术分享技术分享会有连续的一段相同且相同的为一定连续的一段,可证最多有2√n和2√m段,分块处理,对于每个询问可O(√n)解决。

 

代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 using namespace std;
 4 const int M=50009;
 5 int k,prime[M],mu[M],s[M];
 6 bool flag[M];
 7 
 8 int read()
 9 {
10     int x=0; char ch=getchar();
11     while (ch<0 || ch>9) ch=getchar();
12     while (ch>=0 && ch<=9) x=(x<<1)+(x<<3)+ch-48,ch=getchar();
13     return x;
14 }
15 
16 void getmu(int n)
17 {
18     mu[1]=1;
19     int i,j,k,cnt=0;
20     for (i=2;i<n;++i)
21     {
22         if (!flag[i]) prime[++cnt]=i,mu[i]=-1;
23         for (j=1;j<=cnt && (k=i*prime[j])<n;++j)
24         {
25             flag[k]=1;
26             if (!(i%prime[j])) { mu[k]=0; break; }
27             mu[k]=-mu[i];
28         }
29     }
30     for (i=1;i<n;++i) s[i]=s[i-1]+mu[i];
31 }
32 
33 int sum(int n,int m)
34 {
35     if (n>m) swap(n,m);
36     n=n/k,m=m/k;
37     int i,j,ans=0;
38     for (i=1;i<=n;i=j+1)
39     {
40         j=min(n/(n/i),m/(m/i));
41         ans=ans+(s[j]-s[i-1])*(n/i)*(m/i);
42     }
43     return ans;
44 }
45 
46 int main()
47 {
48     getmu(M);
49     for (int T=read();T;--T)
50     {
51         int a=read(),b=read(),c=read(),d=read();k=read();
52         printf("%d\n",sum(b,d)-sum(a-1,d)-sum(c-1,b)+sum(a-1,c-1));
53     }
54     return 0;
55 }

 

 

 

 

 

[HAOI2011]Problem b 题解

标签:void   min   space   ++i   return   color   namespace   while   lag   

原文地址:http://www.cnblogs.com/HHshy/p/6322949.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!