多校 GCD
2016-07-27 11:54
344 查看
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
我们注意观察
gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar),当l固定不动的时候,r=l...nr=l...n时,我们可以容易的发现,随着rr的増大,gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar)是递减的,同时gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar)最多
有log\
1000,000,000log 1000,000,000个不同的值,为什么呢?因为a_{l}al最多也就有log\
1000,000,000log 1000,000,000个质因数
所以我们可以在log级别的时间处理出所有的以L开头的左区间的gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar) 那么我们就可以在n\
log\ 1000,000,000n log 1000,000,000的时间内预处理出所有的gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar)然后我们可以用一个map来记录,gcd值为key的有多少个
然后我们就可以对于每个询问只需要查询对应gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar)为多少,然后再在map
里面查找对应答案即可.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <algorithm>
#include <cmath>
#include <ctime>
#define LL long long
using namespace std;
int a[110000];
//pair.first为求的GCD
//pair.second为区间的R
//vec对应的下标为区间的L
vector<pair<int,int> >vec[110000];
map<int,LL>M;
int main()
{
int T,t=0;
int l,r;
int n,m;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i = 1; i <= n; ++i){
scanf("%d",&a[i]);
vec[i].clear();
}
M.clear();
for(int i = n; i >= 1; i--){
int g = 0;
/*
L+1....R3...R2....R1....R0
L+1....R3区间的GCD相同
L+1....R3+1和L...R3+2和...和L+1....R2的GCD相同
L+1....R2+1和L...R2+2和...和L+1....R1的GCD相同
L+1....R1+1和L...R1+2和...和L+1....R0的GCD相同
假设L+k<R3
__gcd(a[l],[L+1,L+k])和__gcd(a[l],[L+1,R3])相同
所以只需计算__gcd(a[l],[L+1,R3])的gcd就求出了[L,R3]的GCD了,他们相同。
以此类推...
*/
for(int j = 0; j < vec[i+1].size(); ++j){
int x = vec[i+1][j].first;
int y = vec[i+1][j].second;
int d = __gcd(x,a[i]);
if(g==d)continue;
g = d;
vec[i].push_back(make_pair(g,y));
}
//[i,i]区间也是一个GCD
if(g!=a[i])vec[i].push_back(make_pair(a[i],i));
//用map记录gcd值出现了几次
for(int j = 0; j < vec[i].size(); ++j){
//区间[i,vec[i][j].second] 的 gcd 为 vec[i][j].first
if(j+1 != vec[i].size())
M[vec[i][j].first] += (LL)(vec[i][j].second-vec[i][j+1].second);
else{
M[vec[i][j].first] += (LL)(vec[i][j].second-i+1);
}
}
}
scanf("%d",&m);
printf("Case #%d:\n",++t);
while(m--){
scanf("%d%d",&l,&r);
int x = vec[l].size()-1;
for(int i = 0; i < vec[l].size(); ++i){
if(vec[l][i].second < r){
x = i-1;
break;
}
}
printf("%d %lld\n",vec[l][x].first,M[vec[l][x].first]);
}
}
return 0;
}
: 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
我们注意观察
gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar),当l固定不动的时候,r=l...nr=l...n时,我们可以容易的发现,随着rr的増大,gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar)是递减的,同时gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar)最多
有log\
1000,000,000log 1000,000,000个不同的值,为什么呢?因为a_{l}al最多也就有log\
1000,000,000log 1000,000,000个质因数
所以我们可以在log级别的时间处理出所有的以L开头的左区间的gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar) 那么我们就可以在n\
log\ 1000,000,000n log 1000,000,000的时间内预处理出所有的gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar)然后我们可以用一个map来记录,gcd值为key的有多少个
然后我们就可以对于每个询问只需要查询对应gcd(a_{l},a_{l+1},...,a_{r})gcd(al,al+1,...,ar)为多少,然后再在map
里面查找对应答案即可.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <vector>
#include <stack>
#include <map>
#include <algorithm>
#include <cmath>
#include <ctime>
#define LL long long
using namespace std;
int a[110000];
//pair.first为求的GCD
//pair.second为区间的R
//vec对应的下标为区间的L
vector<pair<int,int> >vec[110000];
map<int,LL>M;
int main()
{
int T,t=0;
int l,r;
int n,m;
scanf("%d",&T);
while(T--){
scanf("%d",&n);
for(int i = 1; i <= n; ++i){
scanf("%d",&a[i]);
vec[i].clear();
}
M.clear();
for(int i = n; i >= 1; i--){
int g = 0;
/*
L+1....R3...R2....R1....R0
L+1....R3区间的GCD相同
L+1....R3+1和L...R3+2和...和L+1....R2的GCD相同
L+1....R2+1和L...R2+2和...和L+1....R1的GCD相同
L+1....R1+1和L...R1+2和...和L+1....R0的GCD相同
假设L+k<R3
__gcd(a[l],[L+1,L+k])和__gcd(a[l],[L+1,R3])相同
所以只需计算__gcd(a[l],[L+1,R3])的gcd就求出了[L,R3]的GCD了,他们相同。
以此类推...
*/
for(int j = 0; j < vec[i+1].size(); ++j){
int x = vec[i+1][j].first;
int y = vec[i+1][j].second;
int d = __gcd(x,a[i]);
if(g==d)continue;
g = d;
vec[i].push_back(make_pair(g,y));
}
//[i,i]区间也是一个GCD
if(g!=a[i])vec[i].push_back(make_pair(a[i],i));
//用map记录gcd值出现了几次
for(int j = 0; j < vec[i].size(); ++j){
//区间[i,vec[i][j].second] 的 gcd 为 vec[i][j].first
if(j+1 != vec[i].size())
M[vec[i][j].first] += (LL)(vec[i][j].second-vec[i][j+1].second);
else{
M[vec[i][j].first] += (LL)(vec[i][j].second-i+1);
}
}
}
scanf("%d",&m);
printf("Case #%d:\n",++t);
while(m--){
scanf("%d%d",&l,&r);
int x = vec[l].size()-1;
for(int i = 0; i < vec[l].size(); ++i){
if(vec[l][i].second < r){
x = i-1;
break;
}
}
printf("%d %lld\n",vec[l][x].first,M[vec[l][x].first]);
}
}
return 0;
}
相关文章推荐
- js实现textarea高度根据内容自适应
- 阿尔法狗原理解析
- 从零开始的Android新项目1 - 架构搭建篇
- python网络编程学习笔记(二)
- 栈1--顺序栈
- AngularJS入门之动画
- HP-UX Oracle Ioctl ASYNC_CONFIG error=1
- 当define或者typedef遇到模板
- c服务端通过多线程来处理不同请求
- 1 + 2 + 3 + 4 + ⋯
- 字符串最后一个单词的长度
- 用于学习的APP
- 【通讯术语】NAT
- JSON格式的时间/Date(2367828670431)/格式转为正常的年-月-日 格式的代码
- java实现二叉查找树
- 机房收费系统思路整理
- ubuntu上配置jdk
- 短信黑词
- iOS中如何实现单个页面支持横竖屏(其他页面只能竖屏)
- k短路 SPFA+A*算法 poj 2449