hdu 5726 GCD(线段树+预处理)
2016-07-24 20:20
357 查看
Problem Description
Give 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).
Input
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.
Output
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).
Sample Input
1
5
1 2 4 6 7
4
1 5
2 4
3 4
4 4
Sample Output
Case #1:
1 8
2 4
2 4
6 1
题意:给你n个数字,然后问你有多少个区间[l,r]的gcd等于询问的区间的gcd。
思路:对于查询区间的gcd,直接用线段树做就可以了。gcd有个性质,就是一个数字ai最多是log2(ai)个质因子,由于区间的gcd,随着区间的增大,gcd是单调不增的,所以对于固定的右端点ai,往左扩张,gcd的个数,不会超过log2(ai)个,所以可以直接用map存,枚举右端点,map[i]=gcd(map[i−1],ai),因为map里最多只会有log2(ai)个值。所以可以直接暴力。
Give 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).
Input
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.
Output
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).
Sample Input
1
5
1 2 4 6 7
4
1 5
2 4
3 4
4 4
Sample Output
Case #1:
1 8
2 4
2 4
6 1
题意:给你n个数字,然后问你有多少个区间[l,r]的gcd等于询问的区间的gcd。
思路:对于查询区间的gcd,直接用线段树做就可以了。gcd有个性质,就是一个数字ai最多是log2(ai)个质因子,由于区间的gcd,随着区间的增大,gcd是单调不增的,所以对于固定的右端点ai,往左扩张,gcd的个数,不会超过log2(ai)个,所以可以直接用map存,枚举右端点,map[i]=gcd(map[i−1],ai),因为map里最多只会有log2(ai)个值。所以可以直接暴力。
#include <iostream> #include<cstdio> #include<map> #include<cstring> #include<algorithm> using namespace std; typedef __int64 ll; ll gcd(ll a,ll b) { if(b!=0) return gcd(b,a%b); return a; } struct node { ll l,r,gcd; } tree[1000005]; ll a[100005],ans,cnt; map<ll,ll>temp1,temp2,ans1; void build(ll id,ll l,ll r) { tree[id].l=l,tree[id].r=r; if(l==r) { tree[id].gcd=a[l]; return; } ll mid=(l+r)/2; build(2*id,l,mid); build(2*id+1,mid+1,r); tree[id].gcd=gcd(tree[2*id].gcd,tree[2*id+1].gcd); } ll Query(ll id,ll l,ll r) { if(tree[id].l==l&&tree[id].r==r) return tree[id].gcd; ll mid=(tree[id].l+tree[id].r)/2; if(r<=mid) ans=Query(2*id,l,r); else if(l>=mid+1) ans=Query(2*id+1,l,r); else { ll t1=Query(2*id,l,mid); ll t2=Query(2*id+1,mid+1,r); ans=gcd(t1,t2); } return ans; } int main() { ll t,n,q;cnt=0; scanf("%I64d",&t); while(t--) { temp1.clear(); temp2.clear(); ans1.clear(); scanf("%I64d",&n); for(ll i=1; i<=n; i++) scanf("%I64d",&a[i]); build(1,1,n); temp1[a[1]]++,ans1[a[1]]++; for(int i=2; i<=n; i++) { ll now=a[i]; temp2[now]++; ans1[now]++; for(auto it=temp1.begin(); it!=temp1.end(); it++) { int nex=gcd(now,it->first); ans1[nex]+=it->second; temp2[nex]+=it->second; } temp1.clear(); for(auto it=temp2.begin(); it!=temp2.end(); it++) { temp1[it->first]=it->second; } temp2.clear(); } printf("Case #%I64d:\n",++cnt); scanf("%I64d",&q); for(ll i=1; i<=q; i++) { ll l,r; ans=0; scanf("%I64d%I64d",&l,&r); ll ans=Query(1,l,r); cout<<ans<<" "<<ans1[ans]<<endl; } } return 0; }
相关文章推荐
- Python爬虫进阶三之Scrapy框架安装配置
- 杭电ACM--HDU1020Encoding
- swift8-错误处理
- poj 2778 DNA Sequence
- CSS BACKGROUND汇总
- fprintf函数小记
- Codeforces Round #364 (Div. 2) D As Fast As Possible(数学)
- zsh 的systemctl 智能补齐脚本
- Drawble和Bitmap之间的转换
- css3动画效果小结
- 1445. 回家【推荐】 的题解
- linux下多进程/多线程文件操作详解
- Linux上搭建Jenkins
- Rational Rose
- 安卓学习笔记Ubuntu 16.04 LTS中安卓开发环境的搭建步骤
- Integer与int的种种比较
- 关于SPFA算法
- 百练2815:城堡问题
- Codeforces Round #364 (Div. 2) C They Are Everywhere(滑窗)
- HDU-2012