HDU 5726 GCD (2016多校、二分、ST表处理区间GCD、数学)
题意 : 给出一个有 N 个数字的整数数列、给出 Q 个问询、每次问询给出一个区间、用 ( L、R ) 表示、要你统计这个整数数列所有的子区间中有多少个和 GCD( L ~ R ) 相等、输出 GCD( L ~ R ) 以及子区间个数
分析 :
首先对于给出一个区间要你给出 GCD
这个操作可以使用线段树来做、线段树是可以维护 GCD 的
但是由于这题的静态区间 (即数列里面的数不会被改变)
那么也有另外一种方法来回答区间 GCD 的问询
预处理的复杂度是 O(nlogn) 、问询是 O(1)
即 ST表、类似处理 RMQ 问题那样子把代码改成求 GCD 就行了
其次它还要你给出和问询区间 GCD 一样的子区间的个数
考虑预处理出所有出现的 GCD 到底在多少个不同的子区间出现过
用 map 存一下也能够做到复杂度在 O(nlogn) 内
这个的处理需要用到二分技巧、还有一点数学知识
首先如果固定区间左端点、那么右端点越大、则 GCD 必定单调不增
所以可以考虑枚举所有的位置作为左端点
然后通过二分的方式找出所有以左端点为开头的 GCD 一样的区间
例如 2 4 6 5 1
枚举 2 作为左端点时候、那么第一次二分会二分到 6 的位置
即 2 4 6 的 GCD 都是 2、则 mp[2] += pos(6) - pos(2) + 1 = 3 - 1 + 1 = 3
然后将 GCD 改变一下变成 GCD = gcd( GCD, 5 )
此时 GCD 会变成 1 、那么第二次二分就会二分到 1 的位置
所以 mp[1] = pos(1) - pos(5) + 1 = 2
接下来就以 4 为左端点、以此类推........
但是你可能会有忧虑、即使是这样子的二分、会不会因为二分次数太多超时
那么你考虑一下、对于端点 L 、其数值是 arr[L]
那么以它为左端点的区间的 GCD 必定是 arr[L] 质因子的某些乘积组合
每加入一个能够改变 GCD 的数、则 GCD 必定减少至少两倍
质因子的数量的 log 的、那么每次二分必定不超过 log(1e9) 次
#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)
#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))
#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>
#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;
;
int N, Q;
int arr[maxn];
];
int idx[maxn];
map<int, LL> mp;
inline void init_idx()
{
idx[] = -;
; len<=N; len++)
idx[len] = ((len & (len-)) == ) ? idx[len-] + : idx[len-];
}
inline void init_rmq()
{
; j<=; j++){
; i+(<<(j-))<= N; i++){
dp[i][j] = __gcd(dp[i][j-], dp[i+(<<(j-))][j-]);
}
}
}
int RMQ(int L, int R)
{
];
<<k)+][k]);
}
inline void init_gcd_num()
{
; i<=N; i++){
int j = i;
int GCD = arr[j];
while(j <= N){
int L, R, pos;
L = pos = j;
R = N;
while(L <= R){
);
, pos = mid;
;
}
mp[GCD] += 1LL * (pos - j + );
j = pos + ;
GCD = RMQ(i, j);
}
}
}
int main(void){__stTIME();__IOPUT();
;
sci(nCase);
while(nCase--){
mp.clear();
sci(N);
; i<=N; i++)
sci(arr[i]),
dp[i][] = arr[i];
init_idx();
init_rmq();
init_gcd_num();
sci(Q);
printf("Case #%d:\n", ++Case);
while(Q--){
int L, R;
scii(L, R);
int GCD = RMQ(L, R);
printf("%d %lld\n", GCD, mp[GCD]);
}
}
__enTIME();;}
void __stTIME()
{
#if _TIME
START = clock();
#endif
}
void __enTIME()
{
#if _TIME
END = clock();
cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
#endif
}
void __IOPUT()
{
#if _INPUT
freopen("in.txt", "r", stdin);
#endif
#if _OUTPUT
freopen("out.txt", "w", stdout);
#endif
}
HDU 5726 GCD (2016多校、二分、ST表处理区间GCD、数学)的更多相关文章
- HDU 5727 Necklace ( 2016多校、二分图匹配 )
题目链接 题意 : 给出 2*N 颗珠子.有 N 颗是阴的.有 N 颗是阳的.现在要把阴阳珠子串成一个环状的项链.而且要求珠子的放置方式必须的阴阳相间的.然后给出你 M 个限制关系.格式为 ( A.B ...
- HDU5726 GCD(二分 + ST表)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5726 Description Give you a sequence of N(N≤100, ...
- Codeforces 475D CGCDSSQ 区间gcd值
题目链接 题意 给定一个长度为 \(n\) 的数列 \(a_1,...,a_n\) 与 \(q\) 个询问 \(x_1,...,x_q\),对于每个 \(x_i\) 回答有多少对 \((l,r)\) ...
- 2016多校联合训练1 D题GCD (ST表+二分)
暑假颓废了好久啊...重新开始写博客 题目大意:给定10w个数,10w个询问.每次询问一个区间[l,r],求出gcd(a[l],a[l+1],...,a[r])以及有多少个区间[l',r']满足gcd ...
- HDU 5726 GCD (RMQ + 二分)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5726 给你n个数,q个询问,每个询问问你有多少对l r的gcd(a[l] , ... , a[r]) ...
- HDU 5726 GCD(RMQ+二分)
http://acm.split.hdu.edu.cn/showproblem.php?pid=5726 题意:给出一串数字,现在有多次询问,每次询问输出(l,r)范围内所有数的gcd值,并且输出有多 ...
- HDU 5726 GCD 区间GCD=k的个数
GCD Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submis ...
- HDU 5726 GCD
传送门 GCD Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem ...
- HDU 5726 GCD(DP)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5726 [题目大意] 给出数列An,对于询问的区间[L,R],求出区间内数的GCD值,并且求出GCD ...
随机推荐
- X-UA-Compatibles
今天在看京东网页代码的时候,发现了X-UA-Compatibles 这个元信息属性,不是很清楚,百度了一下,做下记录 X-UA-Compatible 属性是 IE 浏览器在 IE8 版本开始提供的一个 ...
- python 高阶函数 lamdad reduce map
## def use_filer(l):## # 过滤偶数# rest = filter(lambda n: n % 2 != 0, l)# return rest## if __name__ == ...
- 数值优化(Numerical Optimization)学习系列-目录
数值优化(Numerical Optimization)学习系列-目录 置顶 2015年12月27日 19:07:11 下一步 阅读数 12291更多 分类专栏: 数值优化 版权声明:本文为博主原 ...
- CAS实现逻辑(JWT)
由于没有获取正规做CAS的流程,这里根据网上的资料,写了一个自己觉得还可以的方案流程,留着备用 名称介绍: token:用于验证请求是否合法 refreshToken:当token失效后,客户端发送t ...
- 连接云服务器中MySql数据库遇到的问题
使用的免费的云服务器,上面只能下载MySql数据库,不过当云数据库使用绰绰有余了,也就放一些测试数据而已 而且上面只可以部署php项目,.netcore项目部署实现比较麻烦 问题如下: 下载了navi ...
- ubuntu 网卡名称重命名
ubuntu 网卡名称重命名 参考:https://blog.csdn.net/hzj_001/article/details/81587824 biosdevname 和 net.ifnames 两 ...
- jvm之java类加载机制和类加载器(ClassLoader),方法区结构,堆中实例对象结构的详解
一.类加载或类初始化:当程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载.连接.初始化3个步骤来对该类进行初始化.如果没有意外,JVM将会连续完成3个步骤. 二.类加载时机: 1 ...
- vscode调试npm包技巧
官网文档:https://code.visualstudio.com/docs/nodejs/nodejs-debugging node调试方法(日志和debuuger):https://blog.r ...
- CentOS 7自动以root身份登录GNOME桌面
CentOS 7自动以root身份登录GNOME桌面 修改配置文件 /etc/gdm/custom.conf,在 [daemon] 下面添加一下两行 AutomaticLoginEnable=true ...
- 华硕B360主板装机找不到固态硬盘启动
1.开机点按F2进入BIOS中,在security选项卡中选择secure boot menu,secure boot control按Enter选择Disable,按F10保存: 2.电脑重 ...