题目描述
给出长为n的序列A,将其分成k个连续的非空字段
求每一段最大值之间的gcd的最大值
思路
Max_A肯定是逃不过的
所以我们可以枚举Max_A的约数
然后判断序列A是否可以分成等于或超过k段
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int lt[100250], A[100250], g[100250];
int n, m, Maxx, tot;
int Find(int l, int r)
{
int k = 0, Maxn = 0;
for(int i = l; i <= r; i++)
if(A[i] > Maxn)Maxn = A[i], k = i;
return k;
}
int Check(int l, int r, int num)
{
if(l > r)return 0;
int k = Find(l, r);
if(A[k] % num == 0)return Check(l, k - 1, num) + Check(k + 1, r, num) + 1;
if(l == 1)return Check(l, k - 1, num);
if(r == n)return Check(k + 1, r, num);
return max(Check(l, k - 1, num), Check(k + 1, r, num));
}
int main()
{
// freopen("1.txt", "r", stdin);
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
scanf("%d", &A[i]), Maxx = max(A[i], Maxx);
for(int i = 1; i <= (int)sqrt(Maxx); ++i)
if(!(Maxx % i))
{
g[++tot] = i;
if(i * i != n)g[++tot] = Maxx / i;
}
sort(g + 1, g + tot + 1);
for(int i = tot; i > 1; --i)
if(Check(1, n, g[i]) >= m)
{
printf("%d", g[i]);
return 0;
}
printf("1");
return 0;
}