luoguP1890 gcd区间 [st表][gcd]
2024-09-22 01:40:07
题目描述
给定一行n个正整数a[1]..a[n]。
m次询问,每次询问给定一个区间[L,R],输出a[L]..a[R]的最大公因数。
输入输出格式
输入格式:
第一行两个整数n,m。
第二行n个整数表示a[1]..a[n]。
以下m行,每行2个整数表示询问区间的左右端点。
保证输入数据合法。
输出格式:
共m行,每行表示一个询问的答案。
输入输出样例
输入样例#1:
5 3
4 12 3 6 7
1 3
2 3
5 5
输出样例#1:
1
3
7
说明
对于30%的数据,n <= 100, m <= 10
对于60%的数据,m <= 1000
对于100%的数据,1 <= n <= 1000,1 <= m <= 1,000,000
0<=数字大小<=1,000,000,000
序列固定、区间查询===>离线处理===>考虑st表!
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std; const int maxn=;
int n,m;
int stgcd[maxn][],mn[maxn];
int a[maxn]; int gcd(int a,int b){ return b==?a:gcd(b,a%b); } void init(){
mn[]=-;
for(int i=;i<=n;i++){
mn[i]=((i&(i-))==)?mn[i-]+:mn[i-];
stgcd[i][]=a[i];
}
for(int j=;j<=mn[n];j++)
for(int i=;i+(<<j)-<=n;i++){
stgcd[i][j]=gcd(stgcd[i][j-],stgcd[i+(<<(j-))][j-]);
}
} int rmq_gcd(int left,int right){
int k=mn[right-left+];
return gcd(stgcd[left][k],stgcd[right-(<<k)+][k]);
} int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++) scanf("%d",&a[i]);
init();
for(int i=,l,r;i<m;i++){
scanf("%d%d",&l,&r);
printf("%d\n",rmq_gcd(l,r));
}
return ;
}
最新文章
- grep如何忽略.svn目录,以及如何忽略多个目录
- hdu 2873 Bomb Game 博弈论
- hdu 3483 A Very Simple Problem
- 【转】Mac和iOS开发资源汇总—更新于2013-07-19
- POJ 1845 Sumdiv(因子分解+快速幂+二分求和)
- wordpress参考网站
- linux杂记(六)档案权限
- ubuntu下的apache的虚拟主机的配置
- MappedByteBuffer
- python 的生成器,yield的使用
- MySQL Hardware--NUMA与MySQL
- Java内存管理-掌握虚拟机类加载机制(四)
- js 简版双色球 取号
- 函数和常用模块【day04】:内置函数(八)
- IN_ORDER_PLANNING、IN_BOM_CHANGE
- Visual Studio:error MSB8020
- bzoj 3261 最大异或和 可持久化字典树(01树)
- .Net core使用Quartz.Net 实现定时任务
- 免费网站监控服务阿里云监控,DNSPod监控,监控宝,360云监控使用对比
- 10.Linux网卡的配置及详解