GCD (hdu 5726)

GCD

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

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

2016 Multi-University Training Contest1

思路:RMQ+二分

一开始我用的线段树去维护各个区间的gcd但是超时,并且我没有优化。

暴力统计的各个区间的gcd;

后来发现gcd的性质,也就是求数的gcd,这些数的个数越多那么gcd越小,所以从左到右,以某个端点开始的gcd的大小随着区间增大而减小,那么二分统计以某个点为端点的gcd

最多每个端点二分30次。

然后还是超时。

然后改用RMQ基于稀疏表的,查询O(n);

复杂度(n*log(n));

 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<string.h>
 5 #include<stdlib.h>
 6 #include<queue>
 7 #include<map>
 8 #include<math.h>
 9 using namespace std;
10 typedef long long LL;
11 int RMQ[20][100005];
12 int ans[100005];
13 map<int,LL>my;
14 int gcd(int n,int m)
15 {
16         if(m==0)
17                 return n;
18         else  if(n%m==0)
19         {
20                 return m;
21         }
22         else return gcd(m,n%m);
23 }
24 int main(void)
25 {
26         int i,j,k;
27         int n,m;
28         scanf("%d",&k);
29         int ca=0;
30         while(k--)
31         {
32                 my.clear();
33                 scanf("%d",&n);
34                 for(i=1; i<=n; i++)
35                 {
36                         scanf("%d",&ans[i]);
37                 }
38                 for(i=1; i<=n; i++)
39                 {
40                         RMQ[0][i]=ans[i];
41                 }
42                 scanf("%d",&m);
43                 for(i=1; i<20; i++)
44                 {
45                         for(j=1; j<=n; j++)
46                         {
47                                 if(j+(1<<i)-1<=n)
48                                 {
49                                         RMQ[i][j]=gcd(RMQ[i-1][j],RMQ[i-1][j+(1<<(i-1))]);
50                                 }
51                         }
52                 }
53                 for(i=1; i<=n; i++)
54                 {
55                         for(j=i; j<=n;)
56                         {
57                                 int t=log2(j-i+1);
58                                 int ac=gcd(RMQ[t][i],RMQ[t][j-(1<<t)+1]);
59                                 int l=j;
60                                 int r=n;
61                                 int id=0;
62                                 while(l<=r)
63                                 {
64                                         int mid=(l+r)/2;
65                                         int c=log2(mid-i+1);
66                                         int ak=gcd(RMQ[c][i],RMQ[c][mid-(1<<c)+1]);
67                                         if(ak>=ac)
68                                         {
69                                                 id=mid;
70                                                 l=mid+1;
71                                         }
72                                         else r=mid-1;
73                                 }
74                                 my[ac]+=id-j+1;
75                                 j=id+1;
76                         }
77                 }
78                 printf("Case #%d:\n",++ca);
79                 while(m--)
80                 {
81                         int x,y;
82                         scanf("%d %d",&x,&y);
83                         if(x>y)
84                         {
85                             swap(x,y);
86                         }
87                         int ct=log2(y-x+1);
88                         int acc=gcd(RMQ[ct][x],RMQ[ct][y-(1<<ct)+1]);
89                         printf("%d %lld\n",acc,my[acc]);
90                 }
91         }
92         return 0;
93 }
时间: 2024-12-25 11:36:35

GCD (hdu 5726)的相关文章

HDU 5726 GCD 区间GCD=k的个数

GCD Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2742    Accepted Submission(s): 980 Problem Description Give you a sequence of N(N≤100,000) integers : a1,...,an(0<ai≤1000,000,000). There ar

GCD HDU - 1695 (容斥原理)

GCD HDU - 1695 题意:给你5个数a,b,c,d,k.x属于[a,b]y属于[c,d]. 问你有多少对(x,y)的公约数为k.  注意(x,y)和 (y,x)视为同一对,a和c为1. 通过b/k,d/k,等价于把区间除以k,那么就变成了求有多少对(x,y)互素. 欧拉函数+容斥原理. 注意k可能为0. 1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 const int maxn=1

HDU 5726 GCD (RMQ + 二分)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5726 给你n个数,q个询问,每个询问问你有多少对l r的gcd(a[l] , ... , a[r]) 等于的gcd(a[l'] ,..., a[r']). 先用RMQ预处理gcd,dp[i][j] 表示从i开始2^j个数的gcd. 然后用map存取某个gcd所对应的l r的数量. 我们可以在询问前进行预处理,先枚举i,以i为左端点的gcd(a[i],..., a[r])的种类数不会超过log2(n)

HDU 5726 GCD(DP)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5726 [题目大意] 给出数列An,对于询问的区间[L,R],求出区间内数的GCD值,并且求出GCD值与其相等的区间总数 [题解] 首先,固定一个区间的右端点,利用GCD的递减性质,可以求出GCD相等的区间左端点的范围,将其范围的左右端点保存下来,同时,对于每个新产生的区间,以其GCD值为下标的MAP值+1,最后对于每个询问,在其右端点保存的范围中查找,获得其GCD值,同时在MAP中获取该GCD值

HDU 5726 GCD

传送门 GCD Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Problem DescriptionGive you a sequence of $N(N≤100,000)$ integers : $a_1,\cdots,a_n(0<a_i≤1000,000,000)$. There are $Q(Q≤100,000)$ queries. For each query $l

hdu 5726 GCD 倍增+ 二分

题目链接 给n个数, 定义一个运算f[l,r] = gcd(al, al+1,....ar). 然后给你m个询问, 每次询问给出l, r. 求出f[l, r]的值以及有多少对l', r' 使得f[l, r] = f[l', r']. 第一个很简单, 用倍增的思想就可以了. 然后是第二个, 我们枚举每一个左端点i, 显然f[i, j]是只降不增的. 那么我们可以二分找到所有使得f[i, j]下降的值j. 因为gcd每次至少变为原来的二分之一, 而ai最大为1e9. 所以最多只有log2(1e9)个

BestCoder10 1001 Revenge of GCD(hdu 5019) 解题报告

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5019 题目意思:给出 X 和 Y,求出 第 K 个 X 和 Y 的最大公约数. 例如8 16,它们的公约数依次为1 2 4 8,那么第 3 个 GCD(X, Y) = 2,也就是从后往前数第3个公共因子. TLE思路:求出 X 的所有因子(从小到大开始存储),再从后往前枚举这些因子,检查是否也为 Y 的因子,统计到第 K 个数就是答案了......以为可以顺利通过,原来数据量还是非常大滴!!! 正确

Sum Of Gcd(hdu 4676)

Sum Of Gcd Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)Total Submission(s): 738    Accepted Submission(s): 333 Problem Description Given you a sequence of number a1, a2, ..., an, which is a permutation of 1...n

hdu 5726(二分)

GCD Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 1233 Accepted Submission(s): 382 Problem Description Give you a sequence of N(N≤100,000) integers : a1,...,an(0<ai≤1000,000,000). There are Q(Q