Bzoj2301 [HAOI2011]Problem b
Submit: 4476 Solved: 2057
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
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
数学问题 莫比乌斯反演 容斥
如果要求
见→ http://www.cnblogs.com/SilverNebula/p/6582843.html
现在有了下界,只需要在外面套个小容斥即可。
喜闻乐见1A,之后把别的题的代码误交到这边又多WA了一次2333
1 /*by SilverN*/ 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 #include<vector> 8 using namespace std; 9 const int mxn=50010; 10 int read(){ 11 int x=0,f=1;char ch=getchar(); 12 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 int pri[mxn],cnt=0; 17 int mu[mxn],smm[mxn]; 18 bool vis[mxn]; 19 void init(){ 20 mu[1]=1; 21 for(int i=2;i<mxn;i++){ 22 if(!vis[i]){ 23 pri[++cnt]=i;mu[i]=-1; 24 } 25 for(int j=1;j<=cnt && pri[j]*i<mxn;j++){ 26 vis[i*pri[j]]=1; 27 if(i%pri[j]==0){mu[i*pri[j]]=0;break;} 28 mu[i*pri[j]]=-mu[i]; 29 } 30 } 31 for(int i=1;i<mxn;i++)smm[i]=smm[i-1]+mu[i]; 32 return; 33 } 34 int calc(int a,int b){ 35 if(a>b)swap(a,b); 36 int res=0,pos; 37 for(int i=1;i<=a;i=pos+1){ 38 int x=a/i,y=b/i; 39 pos=min(a/x,b/y); 40 res+=(smm[pos]-smm[i-1])*x*y; 41 } 42 return res; 43 } 44 int solve(int x,int y,int k){ 45 return calc(x/k,y/k); 46 } 47 int n,a,b,c,d; 48 int ans=0; 49 int main(){ 50 int i,j,k; 51 init(); 52 n=read(); 53 while(n--){ 54 a=read();b=read();c=read();d=read();k=read(); 55 --a;--c; 56 ans=solve(b,d,k)+solve(a,c,k)-solve(a,d,k)-solve(b,c,k); 57 printf("%d\n",ans); 58 } 59 return 0; 60 }
本文为博主原创文章,转载请注明出处。