BZOJ 2301: [HAOI2011]Problem b(莫比乌斯反演)
2017-07-28 15:02
489 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=2301
题意:
对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。
思路:
先简单介绍一下莫比乌斯反演在数论中的作用:
![](https://images2017.cnblogs.com/blog/1047463/201707/1047463-20170728145653508-549703516.jpg)
那么怎么做这道题呢?
![](https://images2017.cnblogs.com/blog/1047463/201707/1047463-20170728145742493-1465303891.jpg)
接下来我们只需要枚举d就可以了,但是这里还有一个可以优化的地方,我们依次+1枚举d的时候,有时候n/d和m/d是不会改变的,比如说现在n=m=,那么d=3,4,5时n/d和m/d都是不变的,这样一来的话我们可以分块处理,需要计算一下莫比乌斯的前缀和,就可以将3,4,5的值一起计算了,这样一来,枚举的数量将大大减小。具体看代码。
题意:
对于给出的n个询问,每次求有多少个数对(x,y),满足a≤x≤b,c≤y≤d,且gcd(x,y) = k,gcd(x,y)函数为x和y的最大公约数。
思路:
先简单介绍一下莫比乌斯反演在数论中的作用:
![](https://images2017.cnblogs.com/blog/1047463/201707/1047463-20170728145653508-549703516.jpg)
那么怎么做这道题呢?
![](https://images2017.cnblogs.com/blog/1047463/201707/1047463-20170728145742493-1465303891.jpg)
接下来我们只需要枚举d就可以了,但是这里还有一个可以优化的地方,我们依次+1枚举d的时候,有时候n/d和m/d是不会改变的,比如说现在n=m=,那么d=3,4,5时n/d和m/d都是不变的,这样一来的话我们可以分块处理,需要计算一下莫比乌斯的前缀和,就可以将3,4,5的值一起计算了,这样一来,枚举的数量将大大减小。具体看代码。
#include<iostream> #include<algorithm> #include<cstring> #include<cstdio> #include<sstream> #include<vector> #include<stack> #include<queue> #include<cmath> #include<map> #include<set> using namespace std; typedef long long ll; typedef pair<int,int> pll; const int INF = 0x3f3f3f3f; const int maxn = 1e5 + 5; int a, b, c, d, k; bool check[maxn]; int prime[maxn]; int mu[maxn]; int sum[maxn]; void Moblus() { memset(check, false, sizeof(check)); mu[1] = 1; int tot = 0; for (int i = 2; i <= maxn; i++) { if (!check[i]) { prime[tot++] = i; mu[i] = -1; } for (int j = 0; j < tot; j++) { if (i * prime[j] > maxn) { break; } check[i * prime[j]] = true; if (i % prime[j] == 0) { mu[i * prime[j]] = 0; break; } else { mu[i * prime[j]] = -mu[i]; } } } return ; } int solve(int n, int m) { if(n>m) swap(n,m); int ans=0; for(int i=1,last=0;i<=n;i=last+1) { last=min(n/(n/i),m/(m/i)); //分块处理 ans+=(sum[last]-sum[i-1])*(n/i)*(m/i); } return ans; } int main() { //freopen("in.txt","r",stdin); int T; Moblus(); sum[0]=0; for(int i=1;i<=maxn;i++) sum[i]=sum[i-1]+mu[i]; scanf("%d",&T); while(T--) { scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); printf("%d\n",solve(b/k,d/k)-solve(b/k,(c-1)/k)-solve((a-1)/k,d/k)+solve((a-1)/k,(c-1)/k)); } return 0; }
相关文章推荐
- 【BZOJ2301】【HAOI2011】Problem B(莫比乌斯反演)
- BZOJ2301 [HAOI2011]Problem b(莫比乌斯反演)
- [BZOJ2301][HAOI2011]Problem b(莫比乌斯反演)
- BZOJ2301: [HAOI2011]Problem b 莫比乌斯反演
- bzoj 2301 [HAOI2011]Problem b(莫比乌斯反演+分块优化)
- BZOJ 2301 [HAOI2011]Problem b (莫比乌斯反演)
- BZOJ 2301: [HAOI2011]Problem b(莫比乌斯反演,分块,容斥)
- BZOJ 2301 HAOI2011 Problem b 容斥原理+莫比乌斯反演
- [bzoj2301] [HAOI2011]Problem b(莫比乌斯反演)
- BZOJ.2301.[HAOI2011]Problem B(莫比乌斯反演 容斥)
- [BZOJ2301][HAOI2011]Problem b(莫比乌斯反演)
- [BZOJ 2301][HAOI2011] Problem b 莫比乌斯反演
- [BZOJ2301][HAOI2011]Problem b(莫比乌斯反演)
- BZOJ 2301 [HAOI2011]Problem b (分块 + 莫比乌斯反演)
- bzoj 2301 [HAOI2011]Problem b(莫比乌斯反演)
- BZOJ 2301: [HAOI2011]Problem b(莫比乌斯反演 + 容斥原理 + 分块优化)
- BZOJ 2301 [HAOI2011]Problem b (莫比乌斯反演)
- [BZOJ1101&BZOJ2301][POI2007]Zap [HAOI2011]Problem b|莫比乌斯反演
- [BZOJ2301][HAOI2011]Problem b(莫比乌斯反演)
- BZOJ 2301: [HAOI2011]Problem b (莫比乌斯反演)