链接
题目描述
思路
答案必然是最大数的某个约数,那就从大到小枚举
然后看能否分成大于等于k块
判断考虑分治
对于一个区间最大值x,如果它是约数的倍数,那么就直接考虑左右分
如果本身不是,那就考虑找一个左右分块合并进去
代码
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int N = 1e6 + 100,M = 1010;
int n, m, pl, maxn, k, a[N], s[N];
int find(int l,int r)
{
int pl=0,maxn=0;
for(int i = l; i <= r; ++i) if(a[i] > maxn) maxn = a[i], pl = i;
return pl;
}
int pd(int l, int r, int num)
{
if(l > r) return 0;
int pl = find(l, r);
if(a[pl] % num == 0 ) return pd(l, pl - 1, num) + pd(pl + 1, r, num) + 1;
if(l == 1) return pd(l, pl - 1, num );
if(r == n) return pd(pl + 1, r, num );
return max(pd(l, pl - 1,num), pd(pl + 1, r, num));
}
int main ()
{
scanf("%d%d", &n, &k );
for(int i = 1; i <= n; ++i ) scanf("%d", &a[i]), maxn = max(maxn, a[i]);
for(int i = 1; i <= maxn / i; ++i )
{
if(i * i == maxn) s[++m] = i;
else if(maxn % i == 0 ) s[++m] = i, s[++m] = maxn / i;
}
sort(s + 1,s + 1 + m );
for(int i = m; i >= 1; --i )
if(pd(1, n, s[i]) >= k)
{
printf ( "%d",s[i] );
break;
}
return 0;
}