多校 GCD
来源:互联网 发布:linux怎么学 编辑:程序博客网 时间:2024/05/18 02:32
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 numberN , denoting the number of integers.
The second line containsN integers, a1,...,an(0<ai≤1000,000,000) .
The third line contains a numberQ , denoting the number of queries.
For the nextQ lines, i-th line contains two number , stand for the li,ri , stand for the i-th queries.
The first line of each case contains a number
The second line contains
The third line contains a number
For the next
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 forgcd(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) .
For each query, you need to output the two numbers in a line. The first number stands for
Sample Input
151 2 4 6 741 52 43 44 4
Sample Output
Case #1:1 82 42 46 1
我们注意观察
gcd(al,al+1,...,ar),当l固定不动的时候,r=l...n时,我们可以容易的发现,随着r的増大,gcd(al,al+1,...,ar)是递减的,同时gcd(al,al+1,...,ar)最多 有log 1000,000,000个不同的值,为什么呢?因为al最多也就有log 1000,000,000个质因数所以我们可以在log级别的时间处理出所有的以L开头的左区间的gcd(al,al+1,...,ar) 那么我们就可以在n log 1000,000,000的时间内预处理出所有的gcd(al,al+1,...,ar)然后我们可以用一个map来记录,gcd值为key的有多少个 然后我们就可以对于每个询问只需要查询对应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 longusing namespace std;int a[110000];//pair.first为求的GCD//pair.second为区间的R//vec对应的下标为区间的Lvector<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;}
0 0
- 多校 GCD
- 多校&&HDU 5726 GCD
- hdu5726 GCD 多校1
- gcd
- GCD
- GCD
- GCD
- GCD
- GCD
- GCD
- GCD
- GCD
- GCD
- GCD
- GCD
- gcd
- GCD
- GCD
- 【 哈希算法 】
- 项目 网络请求返回InputStream
- ARM的寻址方式
- Unbuntu 12.04 搭建samba服务器
- DSF框架使用(DAO、序列化、注解、服务接口、服务代理)
- 多校 GCD
- 蘑菇街 App 的组件化之路
- SI 添加SVN
- Python学习笔记之IF
- Android之贝塞尔曲线(Bezier)
- centos6 安装redis3
- Android短信验证
- ARM寻址方式
- LeetCode 203. Remove Linked List Elements