【BZOJ】【2301】problem b

莫比乌斯反演/容斥原理

  Orz PoPoQQQ

  PoPoQQQ莫比乌斯函数讲义第一题。

for(i=1;i<=n;i=last+1){
  last=min(n/(n/i),m/(m/i));
  ……
}
这种写法可以O(sqrt(n))枚举所有的n/d,这个枚举除法的取值在莫比乌斯反演中非常常用。
 1 /**************************************************************
 2     Problem: 2301
 3     User: Tunix
 4     Language: C++
 5     Result: Accepted
 6     Time:10964 ms
 7     Memory:2932 kb
 8 ****************************************************************/
 9  
10 //BZOJ 2301
11 #include<cstdio>
12 #include<cstdlib>
13 #include<cstring>
14 #include<iostream>
15 #include<algorithm>
16 #define rep(i,n) for(int i=0;i<n;++i)
17 #define F(i,j,n) for(int i=j;i<=n;++i)
18 #define D(i,j,n) for(int i=j;i>=n;--i)
19 using namespace std;
20  
21 int getint(){
22     int v=0,sign=1; char ch=getchar();
23     while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();}
24     while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();}
25     return v*=sign;
26 }
27 /*******************tamplate********************/
28 const int N=100086;
29 typedef long long LL;
30 int prime[N],mu[N];
31 bool check[N];
32 LL sum[N];
33  
34 void getmu(int n){
35     memset(check,0,sizeof check);
36     mu[1]=1;
37     int tot=0;
38     F(i,2,n){
39         if(!check[i]){
40             prime[tot++]=i;
41             mu[i]=-1;
42         }
43         rep(j,tot){
44             if(i*prime[j]>n)break;
45             check[i*prime[j]]=1;
46             if(i%prime[j]==0){
47                 mu[i*prime[j]]=0;
48                 break;
49             }
50             else mu[i*prime[j]]=-mu[i];
51         }
52     }
53     F(i,1,n) sum[i]=sum[i-1]+mu[i];
54 }
55 LL calc(int m,int n,int k){
56     int i,last;
57     LL re=0;
58     n/=k; m/=k;
59     for(i=1;i<=m && i<=n;i=last+1){
60         last=min(n/(n/i),m/(m/i));
61         re+=(sum[last]-sum[i-1])*(m/i)*(n/i);
62     }
63     return re;
64 }
65 int main(){
66     getmu(N);
67     int T=getint();
68     while(T--){
69         int a=getint(), b=getint(), c=getint(), d=getint(), k=getint();
70         printf("%lld
", calc(b,d,k)-calc(a-1,d,k)-calc(b,c-1,k)+calc(a-1,c-1,k));
71     }
72     return 0;
73 }
View Code

2301: [HAOI2011]Problem b

Time Limit: 50 Sec  Memory Limit: 256 MB
Submit: 1883  Solved: 808
[Submit][Status][Discuss]

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

Sample Output


14
3

HINT

100%的数据满足:1≤n≤50000,1≤a≤b≤50000,1≤c≤d≤50000,1≤k≤50000

Source

[Submit][Status][Discuss]
原文地址:https://www.cnblogs.com/Tunix/p/4278187.html