- 题解
29届(25年)低程B题题解
- @ 2026-6-27 10:58:01
隔了大半年来补低程题的 来了......
首先观察题干,我们可以知道:
一个优秀的小组,实际就是数组中的一个区间,满足区间内所有数的最小公倍数 区间最大值。
即如果区间 满足:
$$\operatorname{max}_{i=l}^{r} a_i < \operatorname{lcm}_{i=l}^{r} a_i$$则称区间 是优秀的。
显而易见的,对于一个不优秀的区间,一定有 区间最大值=区间最小公倍数 ,因此我们可以令其最大值和最小公倍数均为 。
如果该区间的某一个子区间是优秀的,那么该子区间内一定不含 ,因为如果含 ,则一定会有 最小公倍数=最大值=d ,因此我们可以 利用区间最大值分割不优秀区间 ,以找到它的优秀子区间。
考虑如下操作:
维护一个 表示记录的最大值。
从区间 开始进行如下递归:
检查区间长度是否超过 ,如果不超过,直接 。
检查区间长度是否优秀:
如果优秀,更新 为区间长度,然后 。
如果不优秀,找到区间内所有的最大值,利用最大值将区间分割为多个子区间,继续递归检查这些子区间。
最后输出 即可。
递归深度方面:
在第 轮的递归中,令最大值为 ,最小公倍数为 。
如果有第 轮递归,则 ,即最小公倍数与最大值均为 。
在第 轮递归中,新的最大值 一定存在于上一轮递归的区间中,因此一定是上一轮的最小公倍数 的因数,而上一轮的最大值 在本轮已经被去除,因此一定有
如果有第 轮递归,则一定有 。
即:
$$\text{若 } d_{i+2} \text{ 存在,则 } d_{i+1} \le \frac{d_i}{2}$$因此递归深度最多不会超过 。
#include<bits/stdc++.h>
using namespace std;
#define int long long
int Max=1e9+1;
int ma=0;
int gcd(int a,int b)
{
if(b==0)return a;
return gcd(b,a%b);
}
void Try(vector<int> &a,int l,int r)
{
if(r-l+1<=ma)return;
int lcm=a[l];
int m=a[l];
for(int i=l+1;i<=r;i++)
{
m=max(m,a[i]);
int g=gcd(lcm,a[i]);
lcm=min(Max,lcm/g*a[i]);
}
if(m!=lcm)
{
ma=r-l+1;
return;
}
vector<int> s;
s.push_back(l-1);
for(int i=l;i<=r;i++)
{
if(a[i]==m)s.push_back(i);
}
s.push_back(r+1);
int t=s.size();
for(int i=1;i<t;i++)
{
Try(a,s[i-1]+1,s[i]-1);
}
}
void solve()
{
ma=0;
int n;
cin>>n;
vector<int> a(n);
for(auto &i:a)
{
cin>>i;
}
Try(a,0,n-1);
cout<<ma<<"\n";
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
solve();
}
}
0 条评论
目前还没有评论...