bzoj 2301 Problem b - 莫比乌斯反演

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



  题目大意 (如此简洁的题目就不需要我的烂文笔了)

  这是在迎接codeforces div 2一场蓝(灰)之前恭迎的最后的一道水题(一个名为Doggu的数论神犇这么说的)。好了,废话不多说了。

  如果你还没有做过bzoj 1101,那你应该赶紧做一下咯。

  推理和它一毛一样,然后你发现它求的实际上等于一个二维前缀和,于是它便真地成了一道水题了(你基本上不用改动什么,copy过来,二维前缀和加加减减就水掉了)。

Code

  1 /**
  2  * bzoj
  3  * Problem#2301
  4  * Accepted
  5  * Time:14640ms
  6  * Memory:1576k
  7  */
  8 #include <iostream>
  9 #include <cstdio>
 10 #include <ctime>
 11 #include <cmath>
 12 #include <cctype>
 13 #include <cstring>
 14 #include <cstdlib>
 15 #include <fstream>
 16 #include <sstream>
 17 #include <algorithm>
 18 #include <map>
 19 #include <set>
 20 #include <stack>
 21 #include <queue>
 22 #include <vector>
 23 #include <list>
 24 #ifndef WIN32
 25 #define Auto "%lld"
 26 #else
 27 #define Auto "%I64d"
 28 #endif
 29 using namespace std;
 30 typedef bool boolean;
 31 const signed int inf = (signed)((1u << 31) - 1);
 32 const signed long long llf = (signed long long)((1ull << 61) - 1);
 33 const double eps = 1e-6;
 34 const int binary_limit = 128;
 35 #define smin(a, b) a = min(a, b)
 36 #define smax(a, b) a = max(a, b)
 37 #define max3(a, b, c) max(a, max(b, c))
 38 #define min3(a, b, c) min(a, min(b, c))
 39 template<typename T>
 40 inline boolean readInteger(T& u){
 41     char x;
 42     int aFlag = 1;
 43     while(!isdigit((x = getchar())) && x != ‘-‘ && x != -1);
 44     if(x == -1) {
 45         ungetc(x, stdin);
 46         return false;
 47     }
 48     if(x == ‘-‘){
 49         x = getchar();
 50         aFlag = -1;
 51     }
 52     for(u = x - ‘0‘; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - ‘0‘);
 53     ungetc(x, stdin);
 54     u *= aFlag;
 55     return true;
 56 }
 57
 58 const int limit = 5e4;
 59
 60 int n;
 61 int num = 0;
 62 int prime[10000];
 63 int miu[limit + 1];
 64 boolean vis[limit + 1];
 65
 66 inline void Euler() {
 67     memset(vis, false, sizeof(vis));
 68     miu[0] = 0, miu[1] = 1;
 69     for(int i = 2; i <= limit; i++) {
 70         if(!vis[i])    miu[i] = -1, prime[num++] = i;
 71         for(int j = 0; j < num && prime[j] * 1LL * i <= limit; j++) {
 72             int c = prime[j] * i;
 73             vis[c] = true;
 74             if((i % prime[j]) == 0) {
 75                 miu[c] = 0;
 76                 break;
 77             } else {
 78                 miu[c] = -1 * miu[i];
 79             }
 80         }
 81         miu[i] += miu[i - 1];
 82     }
 83 }
 84
 85 inline void init() {
 86     readInteger(n);
 87 }
 88
 89 inline long long calc(int a, int b, int d) {
 90     long long ret = 0;
 91     a /= d, b /= d;
 92     if(a == 0 || b == 0)    return 0;
 93     if(a > b)    swap(a, b);
 94     ret = 0;
 95     for(int i = 1, j; i <= a; i = j + 1) {
 96         j = min(a / (a / i), b / (b / i));
 97         ret += (a / j) * 1LL * (b / j) * (miu[j] - miu[i - 1]);
 98     }
 99     return ret;
100 }
101
102 inline void solve() {
103     int a, b, c, d, e;
104     while(n--) {
105         scanf("%d%d%d%d%d", &a, &b, &c, &d, &e);
106         printf(Auto"\n", calc(b, d, e) - calc(a - 1, d, e) - calc(c - 1, b, e) + calc(a - 1, c - 1, e));
107     }
108 }
109
110 int main() {
111     Euler();
112     init();
113     solve();
114     return 0;
115 }
时间: 2024-10-08 07:30:36

bzoj 2301 Problem b - 莫比乌斯反演的相关文章

bzoj 2301 Problem b 莫比乌斯反演+容斥

题意:对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数 思路:在hdu1695的基础上加上容斥,即:ans=solve(b/k,d/k)-solve((a-1)/k,d/k)-solve((c-1)/k,b/k)+solve((a-1)/k,(c-1)/k),详见代码: /********************************************************* file n

BZOJ 2301 Problem b(莫比乌斯反演+分块优化)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=37166 题意:对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. 思路:本题使用莫比乌斯反演要利用分块来优化,那么每次询问的复杂度降为2*sqrt(n)+2*sqrt(m).注意到 n/i ,在连续的k区间内存在,n/i=n/(i+k).所有对这连续的区间可以一次求出

bzoj 1101 [POI2007]Zap - 莫比乌斯反演

Description FGD正在破解一段密码,他需要回答很多类似的问题:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a ,y<=b,并且gcd(x,y)=d.作为FGD的同学,FGD希望得到你的帮助. Input 第一行包含一个正整数n,表示一共有n组询问.(1<=n<= 50000)接下来n行,每行表示一个询问,每行三个 正整数,分别为a,b,d.(1<=d<=a,b<=50000) Output 对于每组询问,输出到输出文件zap.out一个正

BZOJ 2301 Problem b

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=2301 冬令营听了莫比乌斯,这就是宋老师上课讲的例题咯[今天来实现一下] 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 5 using namespace std; 6 7 inline int in(){ 8 int x=0;char ch=getchar(); 9 while(ch

bzoj 2820 / SPOJ PGCD 莫比乌斯反演

那啥bzoj2818也是一样的,突然想起来好像拿来当周赛的练习题过,用欧拉函数写掉的. 求$(i,j)=prime$对数 \begin{eqnarray*}\sum_{i=1}^{n}\sum_{j=1}^{m}[(i,j)=p]&=&\sum_{p=2}^{min(n,m)}\sum_{i=1}^{\lfloor\frac{n}{p}\rfloor}\sum_{j=1}^{\lfloor\frac{m}{p}\rfloor}[i⊥j]\newline&=&\sum_{p=

BZOJ 2440 完全平方数(莫比乌斯反演+二分查找)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=23362 题意:定义含有平方数因子的数为完全平方数(平方数因子不包含1).求第k个非完全平方数. 思路:我们先求出[1, n]的非完全平方数的个数,然后利用二分来查找正好等于k时的n(注意这样的n可能不止一个,求最左边的).关键是,怎么求出前者,我们可以利用容斥原理,用n - [1, n]内完全平方数的个数,求[1, n]内完全平方数的个数,用容斥发现前面的系数就是

BZOJ2301: [HAOI2011]Problem b 莫比乌斯反演

分析:对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数. 然后对于求这样单个的gcd(x,y)=k的,我们通常采用莫比乌斯反演 但是,时间复杂度是O(n*(n/k))的,当复杂度很坏的时候,当k=1时,退化到O(n^2),超时 然后进行分块优化,时间复杂度是O(n*sqrt(n)) #include<cstdio> #include<cstring> #include<queue

[BZOJ1101&amp;BZOJ2301][POI2007]Zap [HAOI2011]Problem b|莫比乌斯反演

对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a,y<=b,并且gcd(x,y)=d. 我们可以令F[n]=使得n|(x,y)的数对(x,y)个数 这个很容易得到,只需要让x,y中都有n这个因子就好了,也就是[a/n]*[b/n]个数对(向下取整) 然后设题中所要求的为f[n],很容易得知,F[n]=∑f[d](n|d) 莫比乌斯反演可以得到f[n]=∑μ(d/n)F[d](n|d) 这样是O(n),然而数据范围5*10^4显然不能通过 f[n]=∑μ(d/n)[a/d][b/d]

[HAOI2011][bzoj2301] Problem b [莫比乌斯反演+容斥原理+分块前缀和优化]

题面: 传送门 有洛谷就尽量放洛谷链接呗,界面友好一点 思路: 和HDU1695比较像,但是这一回有50000组数据,直接莫比乌斯反演慢慢加的话会T 先解决一个前置问题:怎么处理a,c不是1的情况? 很简单,容斥原理搞之 我们设f(x,y)代表gcd(i,j)==e(1<=i<=x,1<=j<=y)的无序数对(i,j)的个数 那么本题答案相当于f(d,b)-f(c-1,b)-f(a-1,d)+f(a-1,c-1) 再来看反演超时的问题 我们注意到原反演过程中,f(1)==mu(i)