HDU 5726 GCD(RMQ + 二分)
2016-07-20 14:09
323 查看
GCD
Problem DescriptionGive you a sequence of N(N≤100,000)
integers : a1,...,an(0<ai≤1000,000,000).
There are Q(Q≤100,000)
queries. For each query l,r
you have to calculate gcd(al,,al+1,...,ar)
and count the number of pairs(l′,r′)(1≤l<r≤N)such
that gcd(al′,al′+1,...,ar′)
equal gcd(al,al+1,...,ar).
[align=left]Input[/align]
The first line of input contains a number
T,
which stands for the number of test cases you need to solve.
The first line of each case contains a number N,
denoting the number of integers.
The second line contains N
integers, a1,...,an(0<ai≤1000,000,000).
The third line contains a number Q,
denoting the number of queries.
For the next Q
lines, i-th line contains two number , stand for the
li,ri,
stand for the i-th queries.
[align=left]Output[/align]
For each case, you need to output “Case #:t” at the beginning.(with quotes,
t
means the number of the test case, begin from 1).
For each query, you need to output the two numbers in a line. The first number stands for
gcd(al,al+1,...,ar)
and the second number stands for the number of pairs(l′,r′)
such that gcd(al′,al′+1,...,ar′)
equal gcd(al,al+1,...,ar).
[align=left]Sample Input[/align]
1
5
1 2 4 6 7
4
1 5
2 4
3 4
4 4
[align=left]Sample Output[/align]
Case #1:
1 8
2 4
2 4
6 1
题意:给出一个数列 ,m次询问,每次询问 l,r区间内的gcd值 和 与该区间gcd值相同的区间有多少个
分析:
枚举每一个左端点,找每个左端点对应的所有gcd值区间,预处理出来,由于gcd值呈阶梯下降,所以完全可以处理,此时顺便用map统计区间个数
一开始考虑的是用线段树取gcd值,在加上二分处理,但是发现这样做其实复杂度达到了 n*logn*logn*logn ,直接T掉,然后想到用RMQ O(1)去处理gcd值,降下一个logn成功AC
#include<cstring> #include<string> #include<iostream> #include<queue> #include<cstdio> #include<algorithm> #include<map> #include<cstdlib> #include<cmath> #include<vector> //#pragma comment(linker, "/STACK:1024000000,1024000000"); using namespace std; #define INF 0x3f3f3f3f int n; int a[100005]; int dp[100006][30]; int mm[100005]; void initRMQ(int n,int b[]) { mm[0]=-1; for(int i=1;i<=n;i++) { mm[i]=(i&(i-1))==0?mm[i-1]+1:mm[i-1]; dp[i][0]=b[i]; } for(int j=1;j<=mm ;j++) for(int i=1;i+(1<<j)-1<=n;i++) dp[i][j]=__gcd(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } int rmq(int x,int y) { int k=mm[y-x+1]; return __gcd(dp[x][k],dp[y-(1<<k)+1][k]); } int Fr(int gcd,int i) { int l=i,r=n; while(l+1<=r) { int mid=l+r>>1; int g=rmq(i,mid); if(__gcd(g,gcd)>=gcd) l=mid+1; else r=mid-1; } if(__gcd(gcd,rmq(i,l))!=gcd) l--; return l; } int main() { memset(a,1,sizeof a); int T; int ca=1; scanf("%d",&T); while(T--) { scanf("%d",&n); for(int i=1; i<=n; i++) { scanf("%d",&a[i]); } initRMQ(n,a); map<int ,long long >mp; for(int i=1; i<=n; i++) { int gcd=a[i]; int pos=i; while(pos<=n) { int pos1=Fr(gcd,pos); mp[gcd]+=pos1-pos+1; pos=pos1+1; gcd=__gcd(gcd,a[pos]); } } int m; scanf("%d",&m); printf("Case #%d:\n",ca++); while(m--) { int a,b; scanf("%d%d",&a,&b); int gcd=rmq(a,b); printf("%d %lld\n",gcd,mp[gcd]); } } return 0; }
相关文章推荐
- Math方法讲解
- ListView 的使用
- Unity camera.rect 用法
- BootStrap 缩略图
- Android 框架搭建 软件架构 设计模式与系统架构
- /proc详解
- 数据请求的两种方法 get post NSURLConnection请求
- javascript基础学习笔记
- web.xml中监听器配置
- 由system.currentTimeMillis() 获得当前的时间
- 25 C#类的继承
- HDU 5723 Abandoned country 最小生成树,树上期望
- 《精进—如何成为一个很厉害的人》摘录(更新中……)
- tcpdump 使用示例
- 自定义控件之购物车数量加减
- [C#]网格数据导出到Excel,Excel转DataSet
- 欢迎使用CSDN-markdown编辑器
- eclipse在线安装maven插件报错
- BootStrap 页头
- II8部署WCF服务出错