初次拿到题目,有以下思路
用代码实现后,能够解题,但很多情况下会超时
import java.util.Scanner;
public class MaxGcdTimes {
public static void main(String[] args) {
//数据输入
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] arr = new int[n];
int count1 = 0;
for(int i=0 ; i<n ; i++) {
arr[i] = sc.nextInt();
if(arr[i]==1) count1++; //统计数组中有多少个"1"
}
sc.close();
//数据处理
int dist=100010;
if(count1!=0) {
System.out.println(n-count1);
}else {
for(int i=0 ; i<n-1 ; i++) {
for(int j=i+1 ; j<n ; j++ ) {
if(gcd(arr[i],arr[j])==1) {
dist=Math.min(dist,(j-i)); //最终得到最近的互质数之间的距离
}
}
}
if(dist==100010) {
System.out.println(-1);
}else {
System.out.println(n-1+dist);
}
}
}
public static int gcd(int a , int b) {
int m = b;
while(a%b!=0) {
m=a%b;
a=b;
b=m;
}
return b;
}
}
那么就要考虑如何优化了
for(int i=0 ; i<n-1 ; i++) {
for(int j=i+1 ; j<n ; j++ ) {
if(gcd(arr[i],arr[j])==1) {
dist=Math.min(dist,(j-i)); //最终得到最近的互质数之间的距离
break; //此处优化
}
}
}
在内层循环找到第一个互质数后,就无需再往后寻找了,因为找到的就是本轮外层循环中最短距离的互质数,内层循环break即可。
评判结果如下
还是不够,需要继续优化,参考题解后发现需要使用线段树
import java.util.Scanner;
public class _Test2 {
static int N = 100010; //输入数组的最大长度
static Node[] tr = new Node[N * 4]; //树 (节点数组)
static int[] a = new int[N]; //存放输入数组
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int f = 0; //统计数组中1的个数
for (int i = 1; i <= n; ++i) {
a[i] = sc.nextInt();
if (a[i] == 1) f++;
}
if (f != 0) {
System.out.println(n-f);
return;
}
build(1, 1, n);
if (query(1, 1, n) != 1) {
System.out.println(-1);
return;
}
int ans = 0x3f3f3f3f;
for (int i = 1; i <= n; ++i) {
int l = i + 1, r = n + 1;
while (l < r) {
int mid = l + r >> 1;
if (query(1, i, mid) == 1) r = mid;
else l = mid + 1;
}
if (query(1, i, r) == 1) ans = Math.min(ans, r - i);
}
System.out.println(n-1+ans);
}
static int gcd(int a,int b){ //求最大公约数
return b == 0 ? a:gcd(b,a%b);
}
static void pushup(int u) {
tr[u].g = gcd(tr[u << 1].g, tr[u << 1 | 1].g);
}
static void build(int u, int l, int r) { //建树
if (l == r) tr[u] = new Node(l, r, a[r]);
else {
tr[u] = new Node(l, r, 0);
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
}
static int query(int u, int l, int r) { //求区间gcd
if (tr[u].l >= l && tr[u].r <= r) return tr[u].g;
int mid = tr[u].l + tr[u].r >> 1;
if (r <= mid) return query(u << 1, l, r);
else if (l > mid) return query(u << 1 | 1, l, r);
else return gcd(query(u << 1, l, r), query(u << 1 | 1, l, r));
}
static class Node { //节点类
int l, r, g;
public Node(int l, int r, int g) {
this.l = l; //左子
this.r = r; //右子
this.g = g; //区间的最大公约数
}
}
}