BZOJ2301: [HAOI2011]Problem b 莫比乌斯反演
2016-04-27 21:42
405 查看
分析:对于给出的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))
View Code
然后对于求这样单个的gcd(x,y)=k的,我们通常采用莫比乌斯反演
但是,时间复杂度是O(n*(n/k))的,当复杂度很坏的时候,当k=1时,退化到O(n^2),超时
然后进行分块优化,时间复杂度是O(n*sqrt(n))
#include<cstdio> #include<cstring> #include<queue> #include<cstdlib> #include<algorithm> #include<vector> #include<cmath> using namespace std; typedef long long LL; const int N=5e4+5; const int INF=0x3f3f3f3f; bool vis ; int prime ,mu ,cnt; void getmu() { mu[1] = 1; for(int i=2; i<=N-5; i++) { if(!vis[i]) { prime[++cnt] = i; mu[i] = -1; } for(int j=1; j<=cnt&&i*prime[j]<=N-5; j++) { vis[i*prime[j]] = 1; if(i%prime[j]) mu[i*prime[j]] = -mu[i]; else { mu[i*prime[j]] = 0; break; } } } } LL solve(int n,int m,int k){ n/=k,m/=k; int l=min(n,m); LL ans=0; for(int i=1,j;i<=l;i=j+1){ j=min(n/(n/i),m/(m/i)); ans+=1ll*(mu[j]-mu[i-1])*(n/i)*(m/i); } return ans; } int main(){ getmu(); for(int i=1;i<=N-5;++i)mu[i]+=mu[i-1]; int T; scanf("%d",&T); while(T--){ int a,b,c,d,k; scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); printf("%lld\n",solve(b,d,k)-solve(b,c-1,k)-solve(a-1,d,k)+solve(a-1,c-1,k)); } return 0; }
View Code
相关文章推荐
- java中final与static的区别
- 队列和栈
- Java基础
- 2015级C++第10、11周实践项目 继承和派生
- 内存泄露会导致程序可用内存耗尽,然后崩溃
- poj2793 素数和
- Xamarin.Forms WebView
- 牛客网今日头条笔试详解
- 搭建gpu的theano
- C++学习(一)——标准库类型之string全解析
- 博客开通,记一下自己的用户名由来
- 再谈谈列表元素的删除
- 使用javaFX编辑的学生管理系统
- 斯坦福第十二课:支持向量机(Support Vector Machines)
- php整理(四): mysql
- 进程间的通信(互斥锁、条件变量、读写锁、文件锁、信号灯)
- InetAddress.getLocalHost()详解及异常处理
- hdu5093Battle ships(二分图)
- Hadoop之MapReduce的HelloWorld(七)
- CPU流水线的探秘之旅