65,108
社区成员
你现在有一堆正整数,这些正整数的数量为nn,并且数量为n依次排成一排。对于这些正整数 a1,a2,a3,…,ana1,a2,a3,…,an,它们的范围十分小。今天你突发奇想,想到了一些询问,对于这些询问:
每次给定两个整数 l,r,1≤l≤r≤nl,r,1≤l≤r≤n。
找到这个区间的最大值 mm。
统计 al,al+1,…,ar−1,aral,al+1,…,ar−1,ar 中有多少个数满足 lcm(ai,m)=ai×mlcm(ai,m)=ai×m。这里 lcm(a,b)lcm(a,b) 表示 aa 和 b 的最小公倍数。
第一行两个整数 n, q,依次表示整数的个数以及询问的次数。
第二行 n 个整数a1,a2,…,ana1,a2,…,an。
接下来 q 行,每行两个正整数 li,rili,ri,表示询问的区间。
输出qq行每行一个整数,表示每次查询的结果
#include <bits/stdc++.h>
using namespace std;
// 计算最大公约数
int gcd(int a, int b) {
if(a<b) swap(a,b);
return (b==0?a:gcd(b,a%b));
}
// 找到区间[l, r]的最大值
int max_in_array(int * arr,int l,int r) {
int * a2=arr;
sort(a2+l-1,a2+r);
return a2[r];
}
// 处理询问
int ask(int * arr,int l,int r) {
int m=max_in_array(arr,l,r),s=0;
for (int i=l;i<=r;++i)
s+=bool(gcd(arr[i],m));
return s;
}
int main() {
int n=0,q=0;
cin >> n >> q;
int a[n]={};
for (int i=0;i<n;i++)
cin >> a[i];
while (q--)
{
int l=0,r=0;cin >> l >> r;
cout << ask(a,l-1,r-1) << endl;
}
}
部分测试点依然显示超时,求大佬指点!!!!!!!!!!!!!!!!!!!!!!
没有给定数据范围,不好说什么算法效率最高。
只说你的代码的问题:
一是gcd使用除法而且递归,效率很低。
二是求最大数m没必要sort,顺序扫描是O(n)算法,sort哪有O(n)呢,更糟糕的是sort可能改变输入序列,你的后续求解都是错的了。
实际上"满足 lcm(ai,m)=ai×m"这条件说明要么ai、m之一为1、要么其一为质数并且大数不能整除以小数(比如5、6),所以一个可能的优化是输入时就求出每个数是否质数并记录下来,但是如果数据范围很大的话这个方法不行(不过题目中说了“它们的范围十分小”)。