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一个正整数,表示满足条件的整数对数。

Sample Input

2
4 5 2
6 4 3

Sample Output

3
2
//对于第一组询问,满足条件的整数对有(2,2),(2,4),(4,2)。对于第二组询问,满足条件的整数对有(
6,3),(3,3)。



  题目大意 (这道题够短了吧,不需要大意了)

  这道题的目标是求

  根据gcd的性质,等价于求

  然后看看上一道题的“套路”,发现它的解法2可以支持多组数据。然后思考,发现莫比乌斯函数和欧拉函数有类似的性质:。赶紧抓过来化简式子。

  

  然后又得到了这个优美的式子。然后发现莫比乌斯函数的系数的取值并不多,所以可以分段求值,然后就可以把这道题水掉了。

  (说实话,我并不觉得这算莫比乌斯反演,只是用到了莫比乌斯函数的性质罢了。当个入门题练练手吧)

Code

  1 /**
  2  * bzoj
  3  * Problem#1101
  4  * Accepted
  5  * Time:8956ms
  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 a, b, d;
 62 int num = 0;
 63 int prime[10000];
 64 int miu[limit + 1];
 65 boolean vis[limit + 1];
 66
 67 inline void Euler() {
 68     memset(vis, false, sizeof(vis));
 69     miu[0] = 0, miu[1] = 1;
 70     for(int i = 2; i <= limit; i++) {
 71         if(!vis[i])    miu[i] = -1, prime[num++] = i;
 72         for(int j = 0; j < num && prime[j] * 1LL * i <= limit; j++) {
 73             int c = prime[j] * i;
 74             vis[c] = true;
 75             if((i % prime[j]) == 0) {
 76                 miu[c] = 0;
 77                 break;
 78             } else {
 79                 miu[c] = -1 * miu[i];
 80             }
 81         }
 82         miu[i] += miu[i - 1];
 83     }
 84 }
 85
 86 inline void init() {
 87     readInteger(n);
 88 }
 89
 90 long long res;
 91
 92 inline void solve() {
 93     while(n--) {
 94         readInteger(a);
 95         readInteger(b);
 96         readInteger(d);
 97         a /= d, b /= d;
 98         if(a > b)    swap(a, b);
 99         res = 0;
100         for(int i = 1, j; i <= a; i = j + 1) {
101             j = min(a / (a / i), b / (b / i));
102             res += (a / j) * 1LL * (b / j) * (miu[j] - miu[i - 1]);
103         }
104         printf(Auto"\n", res);
105     }
106 }
107
108 int main() {
109     Euler();
110     init();
111     solve();
112     return 0;
113 }
时间: 2024-10-14 01:58:26

bzoj 1101 [POI2007]Zap - 莫比乌斯反演的相关文章

BZOJ1101: [POI2007]Zap(莫比乌斯反演)

1101: [POI2007]Zap Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2951  Solved: 1293[Submit][Status][Discuss] Description FGD正在破解一段密码,他需要回答很多类似的问题:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a,y<=b,并且gcd(x,y)=d.作为FGD的同学,FGD希望得到你的帮助. Input 第一行包含一个正整数n,表示一共有n组询问.(1

bzoj 1101: [POI2007]Zap

裸的莫比乌斯反演 1 #include<bits/stdc++.h> 2 #define N 100005 3 #define M 10000005 4 #define LL long long 5 #define inf 0x3f3f3f3f 6 using namespace std; 7 inline int ra() 8 { 9 int x=0,f=1; char ch=getchar(); 10 while (ch<'0' || ch>'9') {if (ch=='-')

BZOJ 1101 [POI2007]Zap(莫比乌斯反演)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1101 [题目大意] 求[1,n][1,m]内gcd=k的情况 [题解] 考虑求[1,n][1,m]里gcd=k 等价于[1,n/k][1,m/k]里gcd=1 考虑求[1,n][1,m]里gcd=1 结果为sum(miu[d]*(n/d)*(m/d)) 预处理O(n^1.5) 由于n/d只有sqrt(n)种取值,所以可以预处理出miu[]的前缀和 询问时分段求和 [代码] #incl

BZOJ 1101([POI2007]Zap-满足x&lt;=a&amp;&amp;y&lt;=b&amp;&amp;gcd(x,y)=d的数对个数)

1101: [POI2007]Zap Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1646  Solved: 577 [Submit][Status][Discuss] Description FGD正在破解一段密码,他需要回答很多类似的问题:对于给定的整数a,b和d,有多少正整数对x,y,满足x<=a,y<=b,并且gcd(x,y)=d.作为FGD的同学,FGD希望得到你的帮助. Input 第一行包含一个正整数n,表示一共有n组询问.(

bzoj 1101 Zap —— 莫比乌斯反演

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1101 直接莫比乌斯反演. 代码如下: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; int const xn=5e5+5; int pri[xn],cnt,mu[xn]; bool vis[xn]; int rd()

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 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 22 5 1 5 11 5 1 5 2 Sample Output 143 HINT 100%的数据满足:1≤n≤50000,1≤a≤b≤50000

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]内完全平方数的个数,用容斥发现前面的系数就是

bzoj 3529 [Sdoi2014]数表 (莫比乌斯反演+树状数组+离线)

题目大意:有一张$n*m$的数表,第$i$行第$j$列的数是同时能整除$i,j$的所有数之和,求数表内所有不大于A的数之和 先是看错题了...接着看对题了发现不会做了...刚了大半个下午无果 看了Po姐的题解(Orzzz)才搞懂这道题,搞清楚了莫比乌斯反演的两种经典的卷积形式的不同之处 令$\sigma(i)$表示i的约数个数和 如果去掉A这个限制,则题目是让我们求$\sum_{i=1}^{n}\sum_{j=1}^{m}\sigma(gcd(i,j))$ 考虑如何正确转化式子,让我们能够把不大