HDU5726 GCD(二分 + ST表)
题目
Source
http://acm.hdu.edu.cn/showproblem.php?pid=5726
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个数的序列,多次询问有多少个区间GCD值等于某个区间的gcd值。
任何一个区间不同的GCD个数是log级别的,因为随着右端点向右延伸GCD是单调不增的,而每次递减GCD至少除以2。
考虑固定左端点,最多就nlogn种GCD,可以直接把所有区间GCD值预处理出来,用map存储各种GCD值的个数,查询时直接输出。
具体是这样处理的:枚举左端点,进行若干次二分查找,看当前GCD值最多能延伸到哪儿,进而统计当前GCD值的数量。
而求区间GCD,用ST表,预处理一下,就能在O(1)时间复杂度求出任意区间的gcd了。
代码
#include<cstdio>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std; int gcd(int a,int b){
while(b){
int t=b;
b=a%b;
a=t;
}
return a;
} int n,st[17][111111];
void init(){
for(int i=1; i<17; ++i){
for(int j=1; j<=n; ++j){
if(j+(1<<i)-1>n) continue;
st[i][j]=gcd(st[i-1][j],st[i-1][j+(1<<i-1)]);
}
}
}
int logs[111111];
int query(int a,int b){
int k=logs[b-a+1];
return gcd(st[k][a],st[k][b-(1<<k)+1]);
} int main(){
for(int i=1; i<=100000; ++i){
logs[i]=log2(i)+1e-6;
}
int t;
scanf("%d",&t);
for(int cse=1; cse<=t; ++cse){
scanf("%d",&n);
for(int i=1; i<=n; ++i){
scanf("%d",&st[0][i]);
} init(); map<int,long long> rec;
for(int i=1; i<=n; ++i){
int g=st[0][i],j=i;
while(j<=n){
int l=j,r=n;
while(l<r){
int mid=l+r+1>>1;
if(query(i,mid)==g) l=mid;
else r=mid-1;
}
rec[g]+=(l-j+1);
j=l+1;
g=query(i,j); }
} printf("Case #%d:\n",cse);
int q,a,b;
scanf("%d",&q);
while(q--){
scanf("%d%d",&a,&b);
int g=query(a,b);
printf("%d %lld\n",g,rec[g]);
}
}
return 0;
}
HDU5726 GCD(二分 + ST表)的更多相关文章
- BZOJ4556:[TJOI\HEOI2016]字符串(后缀数组,主席树,二分,ST表)
Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开箱 ...
- BZOJ3166 [Heoi2013]Alo 【可持久化trie树 + 二分 + ST表】
题目 Welcome to ALO ( Arithmetic and Logistic Online).这是一个VR MMORPG , 如名字所见,到处充满了数学的谜题. 现在你拥有n颗宝石,每颗宝石 ...
- [BZOJ4310] 跳蚤 - 后缀数组,二分,ST表
[BZOJ4310] 跳蚤 Description 首先,他会把串分成不超过 \(k\) 个子串,然后对于每个子串 \(S\) ,他会从 \(S\) 的所有子串中选择字典序最大的那一个,并在选出来的 ...
- Codeforces 359D Pair of Numbers | 二分+ST表+gcd
题面: 给一个序列,求最长的合法区间,合法被定义为这个序列的gcd=区间最小值 输出最长合法区间个数,r-l长度 接下来输出每个合法区间的左端点 题解: 由于区间gcd满足单调性,所以我们可以二分区间 ...
- ZJOI2018 胖 二分 ST表
原文链接https://www.cnblogs.com/zhouzhendong/p/ZJOI2018Day2T2.html 题目传送门 - BZOJ5308 题目传送门 - LOJ2529 题目传送 ...
- BZOJ 5308 [ZJOI2018] Day2T2 胖 | 二分 ST表
题目链接 LOJ 2529 BZOJ 5308 题解 这么简单的题 为什么考场上我完全想不清楚 = = 对于k个关键点中的每一个关键点\(a\),二分它能一度成为哪些点的最短路起点(显然这些点在一段包 ...
- BZOJ3473:字符串(后缀数组,主席树,二分,ST表)
Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一 ...
- BZOJ 3230 相似子串 | 后缀数组 二分 ST表
BZOJ 3230 相似子串 题面 题解 首先我们要知道询问的两个子串的位置. 先正常跑一遍后缀数组并求出height数组. 对于每一个后缀suffix(i),考虑以i开头的子串有多少是之前没有出现过 ...
- BZOJ3230 相似子串[后缀数组+二分+st表]
BZOJ3230 相似子串 给一个串,查询排名i和j的子串longest common suffix和longest common prefix 思路其实还是蛮好想的,就是码起来有点恶心.可以发现后缀 ...
随机推荐
- UbuntuLinux安装Mysql
1.安装Mysql5.7 方法:手动安装5.7 One: $ wget http://dev.mysql.com/get/mysql-apt-config_0.6.0-1_all.deb 下载 ...
- NYOJ题目1047欧几里得
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAskAAAIcCAIAAACLpKQmAAAgAElEQVR4nO3dv1LjOsMH4O8m6LkQ6l ...
- NYOJ题目839合并
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAskAAAKgCAIAAADmrHcoAAAgAElEQVR4nO3dO1LsOheG4X8S5AyE2A
- Android缓存学习入门(二)
本文主要包括以下内容 内存缓存策略 文件缓存策略 内存缓存策略 当有一个图片要去从网络下载的时候,我们并不会直接去从网络下载,因为在这个时代,用户的流量是宝贵的,耗流量的应用是不会得到用户的青睐的.那 ...
- 动手动脑及java程序之用消息框进行数的运算
动手动脑 自信成就人生 动手动脑1 ✿仔细阅读示例: EnumTest.java,运行它,分析运行结果? package demo; public class Test { publi ...
- Mac系统下使用VirtualBox虚拟机安装win7--第一步 安装vbox虚拟机
Mac系统下使用VirtualBox虚拟机安装win7操作步骤: 第一步 安装vbox虚拟机 1.先下载vbox,下载地址:: https://www.virtualbox.org/wiki/Down ...
- JavaScript基础——使用数组
Array对象提供存储和处理一组其他对象的一种手段.数组可以存储数值.字符串或其他JavaScript对象.创建JavaScript数组有几种不同的方法.例如,下面的语句穿件同样的驻足的3个相同的版本 ...
- Java 解析XML的几种方法
XML现在已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交互带来了极大的方便. XML在不同的语言里解析方式都是一样的,只不过实现的语法不同而已. 基本的解析方式 ...
- C++杂记
变量就是一个地址,同进程内可以直接访问,要做好线程之间的同步就是了.——摘自CSDN 2015-06-18 16:58:10(注:注意变量的生命周期(作用域就可以不在意))
- 【JAVA多线程中使用的方法】
一.sleep和wait的区别. 1.wait可以指定时间,也可以不指定. 而sleep必须制定. 2.在同步的时候,对于CPU的执行权和以及锁的处理不同. wait:释放执行权,释放锁. sleep ...