GCD

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2530    Accepted Submission(s): 895

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
 
Author
HIT
 
Source
 题意:给你n个数字组成的序列(n<=1e5),接下来q(<=1e5)个询问,每个询问包括一个区间[l,r]。求该区间内数字的GCD,以及整个[1,n]区间上有多少个子区间GCD等于该区间GCD;
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define MM(a,b) memset(a,b,sizeof(a));
#define inf 0x7f7f7f7f
#define FOR(i,n) for(int i=1;i<=n;i++)
#define CT continue;
#define PF printf
#define SC scanf
const int mod=1000000007;
const int N=3*1e5+10; int n,a[N],l[N],r[N]; struct node{
int l,r;
ll sum,lazy;
int gcdn;
void fun(ll v){
this->lazy+=v;
sum+=v*(r-l+1);
}
int mid(){
return (l+r)>>1;
}
}tree[4*N],tree2[4*N]; int gcd(int a,int b)
{
if(b==0) return a;
else return gcd(b,a%b);
} void build(int k,int l,int r)
{
tree[k].l=l;tree[k].r=r;
if(l==r)
{
tree[k].gcdn=a[l];
return;
}
int mid=(l+r)>>1;
build(2*k,l,mid);
build(2*k+1,mid+1,r);
tree[k].gcdn=gcd(tree[2*k].gcdn,tree[2*k+1].gcdn);
} ll query(int k,int l,int r)
{
if(l<=tree[k].l&&tree[k].r<=r) return tree[k].gcdn;
else {
int mid=tree[k].mid();
int gcdk=0;
if(l<=mid) gcdk=query(2*k,l,r);
if(r>mid) gcdk=gcdk==0?query(2*k+1,l,r):gcd(gcdk,query(2*k+1,l,r));
return gcdk;
}
} map<int,ll> tmp,tmpnext,ans;
map<int,ll>::iterator it; void init()
{
tmp.clear();ans.clear();
for(int i=1;i<=n;i++)
{
tmpnext.clear();
tmpnext[a[i]]++;
for(it=tmp.begin();it!=tmp.end();++it)
{
int k=gcd(a[i],it->first);
tmpnext[k]+=it->second;
}
for(it=tmpnext.begin();it!=tmpnext.end();it++)
ans[it->first]+=it->second;
tmp=tmpnext;
}
} int main()
{
int cas,q,kk=0;
scanf("%d",&cas);
while(cas--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
build(1,1,n);
init();
scanf("%d",&q);
for(int i=1;i<=q;i++) scanf("%d%d",&l[i],&r[i]);
printf("Case #%d:\n",++kk);
for(int i=1;i<=q;i++)
{
int k=query(1,l[i],r[i]);
printf("%d %lld\n",k,ans[k]);
}
}
return 0;
}

题解链接:  

我们注意观察gcd(a_{l},a_{l+1},...,a_{r})gcd(a​l​​,a​l+1​​,...,a​r​​),当l固定不动的时候,r=l...nr=l...n时,我们可以容易的发现,随着rr的増大,gcd(a_{l},a_{l+1},...,a_{r})gcd(a​l​​,a​l+1​​,...,a​r​​)是递减的,同时gcd(a_{l},a_{l+1},...,a_{r})gcd(a​l​​,a​l+1​​,...,a​r​​)最多 有log\ 1000,000,000log 1000,000,000个不同的值,为什么呢?因为a_{l}a​l​​最多也就有log\ 1000,000,000log 1000,000,000个质因数

所以我们可以在log级别的时间处理出所有的以L开头的左区间的gcd(a_{l},a_{l+1},...,a_{r})gcd(a​l​​,a​l+1​​,...,a​r​​)

那么我们就可以在n\ log\ 1000,000,000n log 1000,000,000的时间内预处理出所有的gcd(a_{l},a_{l+1},...,a_{r})gcd(a​l​​,a​l+1​​,...,a​r​​)

然后我们可以用一个map来记录,gcd值为key的有多少个 然后我们就可以对于每个询问只需要查询

对应gcd(a_{l},a_{l+1},...,a_{r})gcd(a​l​​,a​l+1​​,...,a​r​​)为多少,然后再在map 里面查找对应答案即可.

错因分析:1.没能正确发现对于一个a(<=1e9)他的质因数个数是loga级别的,因为比如2*2*3*5.....=a,则左边至多loga个元素,

最新文章

  1. oracle问题
  2. oracle安装不容易啊
  3. 怎么运用好ZBrush中Magnify膨胀笔刷
  4. SpringMvc 相关,bean map转换,百度天气,base64.js,jsBase64.java;
  5. HDUOJ----2571(命运)(简单动态规划)
  6. 初探 iOS8 中的 Size Class
  7. LVM pvcreate,vgcreate,lvcreate,mkfs
  8. NHibernate联合主键详细示例
  9. linux下使用autoconf制作Makefile
  10. 【问题汇总】ScrollView嵌套ListView的问题
  11. zigbee端口的理解
  12. vue 列表选中 v-for class
  13. ES脑裂问题
  14. go语言之进阶篇接口的定义和实现以及接口的继承
  15. c语言程序与设计第三版-苏小红--第一轮学习笔记、难点整理
  16. linux文件锁flock【转】
  17. babel-polyfill使用简介
  18. Linux Shell 与Linux常用命令
  19. Codeforces Round #327 (Div2) A~E
  20. windows技术

热门文章

  1. springboot指定redis库编号配置实现
  2. Scala学习八——继承
  3. Scala学习四——映射和数组
  4. Bootstrap3基础教程 01 概述
  5. EasyUI_DataGrid数据操作
  6. MVC4中使用EntityFramework
  7. JS基础_条件分支语句:switch语句
  8. Js的原型和原型链讲解
  9. go语言json转map
  10. 解决办法:Message: 对实体 &quot;useUnicode&quot; 的引用必须以 &#39;;&#39; 分隔符结尾