题目

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表)的更多相关文章

  1. BZOJ4556:[TJOI\HEOI2016]字符串(后缀数组,主席树,二分,ST表)

    Description 佳媛姐姐过生日的时候,她的小伙伴从某东上买了一个生日礼物.生日礼物放在一个神奇的箱子中.箱子外边写了一个长为n的字符串s,和m个问题.佳媛姐姐必须正确回答这m个问题,才能打开箱 ...

  2. BZOJ3166 [Heoi2013]Alo 【可持久化trie树 + 二分 + ST表】

    题目 Welcome to ALO ( Arithmetic and Logistic Online).这是一个VR MMORPG , 如名字所见,到处充满了数学的谜题. 现在你拥有n颗宝石,每颗宝石 ...

  3. [BZOJ4310] 跳蚤 - 后缀数组,二分,ST表

    [BZOJ4310] 跳蚤 Description 首先,他会把串分成不超过 \(k\) 个子串,然后对于每个子串 \(S\) ,他会从 \(S\) 的所有子串中选择字典序最大的那一个,并在选出来的 ...

  4. Codeforces 359D Pair of Numbers | 二分+ST表+gcd

    题面: 给一个序列,求最长的合法区间,合法被定义为这个序列的gcd=区间最小值 输出最长合法区间个数,r-l长度 接下来输出每个合法区间的左端点 题解: 由于区间gcd满足单调性,所以我们可以二分区间 ...

  5. ZJOI2018 胖 二分 ST表

    原文链接https://www.cnblogs.com/zhouzhendong/p/ZJOI2018Day2T2.html 题目传送门 - BZOJ5308 题目传送门 - LOJ2529 题目传送 ...

  6. BZOJ 5308 [ZJOI2018] Day2T2 胖 | 二分 ST表

    题目链接 LOJ 2529 BZOJ 5308 题解 这么简单的题 为什么考场上我完全想不清楚 = = 对于k个关键点中的每一个关键点\(a\),二分它能一度成为哪些点的最短路起点(显然这些点在一段包 ...

  7. BZOJ3473:字符串(后缀数组,主席树,二分,ST表)

    Description 给定n个字符串,询问每个字符串有多少子串(不包括空串)是所有n个字符串中至少k个字符串的子串? Input 第一行两个整数n,k. 接下来n行每行一个字符串. Output 一 ...

  8. BZOJ 3230 相似子串 | 后缀数组 二分 ST表

    BZOJ 3230 相似子串 题面 题解 首先我们要知道询问的两个子串的位置. 先正常跑一遍后缀数组并求出height数组. 对于每一个后缀suffix(i),考虑以i开头的子串有多少是之前没有出现过 ...

  9. BZOJ3230 相似子串[后缀数组+二分+st表]

    BZOJ3230 相似子串 给一个串,查询排名i和j的子串longest common suffix和longest common prefix 思路其实还是蛮好想的,就是码起来有点恶心.可以发现后缀 ...

随机推荐

  1. 双栈排序(codevs 1170)

    题目描述 Description Tom最近在研究一个有趣的排序问题.如图所示,通过2个栈S1和S2,Tom希望借助以下4种操作实现将输入序列升序排序. 操作a 如果输入序列不为空,将第一个元素压入栈 ...

  2. Mysql基于GTIDs的复制

    通过GTIDs[global transaction identifiers],可以标识每一个事务,并且可以在其一旦提交追踪并应用于任何一个Slave上:这样 就不需要像BinaryLog复制依赖Lo ...

  3. 一般处理程序获取session值

    1.要在一般处理程序中获取其他页面的session值,需要引用名空间: using System.Web.SessionState; 2.然后继承一个接口:IRequiresSessionState, ...

  4. ASP.NET MVC中Controller返回值类型ActionResult

    1.返回ViewResult视图结果,将视图呈现给网页 public class TestController : Controller { //必须存在Controller\Test\Index.c ...

  5. 设计模式学习之备忘录模式(Memento,行为型模式)(19)

    假如我们已经记录一个人的个人信息,但是发现信息写错了,然后我先备份下再去修改,结果发现原来的信息是正确的,于是我就看备份的个人信息还原到初始的状态,下面我们用代码去实现 class Program { ...

  6. Algorithms, Part I by Kevin Wayne, Robert Sedgewick

    Welcome to Algorithms, Part I 前言 昨天在突然看到了Coursera上Robert Sedgewick讲的Algorithms,Part II看了一些,甚是爽快,所以又去 ...

  7. [Win32命令行] 更改提示符字符串(PS1)

    当进入的目录比较深时, cmd的提示符几乎会占据整行, 很烦, 于是Google之... 参考: A better PROMPT for CMD.EXE ... 更改方式:        1. pro ...

  8. 用.NET开发通用Windows App

    (此文章同时发表在本人微信公众号"dotNET每日精华文章",欢迎右边二维码来关注.) 题记:随着Windows 10的正式发布,作为.NET开发人员应该开始或多或少了解一下通用( ...

  9. list[C++]

    //双向链表 #include <iostream> using namespace std; #include <list> int main(int argc, const ...

  10. 写给自己的web开发资源

    web开发给我的感觉就是乱七八糟,而且要学习感觉总是会有东西要学习,很乱很杂我也没空搞,(其实学习这个的方法就是去用它,什么你直接用?学过js么学过jquery么?哈哈,我没有系统的看完过,但是也做出 ...