P4411
题目传送门
题意:从头到尾选数,相邻两个数的
30 pts
相信很多同学的第一想法是 DP。一维
下面是代码实现,就不加注释了。(看一看前面的就知道)
#include<bits/stdc++.h>
using namespace std;
int n,l,a[50001],f[50001],ans=1;
inline void init()
{
cin>>n>>l;
for(int i=1;i<=n;i++)cin>>a[i],f[i]=1;
}
inline void solve()
{
for(int i=2;i<=n;i++)
{
for(int j=1;j<i;j++)if(__gcd(a[i],a[j])>=l)f[i]=max(f[i],f[j]+1);
ans=max(ans,f[i]);
}
cout<<ans;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
init(),solve();
return 0;
}
100 pts
我们可以发现,题目中的
而对
由于
注意:由于此题空间很小,如果数组的第二维开得太大了,就会MLE。这里经过计算后,
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
for(int j=1;j*j<=x;j++)if(x%j==0)
{
if(j>=l)a[i][++t[i]]=j;
if(x/j>=l&&j*j!=x)a[i][++t[i]]=x/j;
}
}
可以发现这相当于一个一个的组,在同一个组的数是可以用前面的更新后面的,而小于
可以对每一个组开一个数组,表示这个组中目前的最大值。对于每个数,从它所在的所有组中选最大值,
for(int i=1;i<=n;i++)
{
int sum=0;
for(int j=1;j<=t[i];j++)sum=max(sum,maxn[a[i][j]]+1);
ans=max(ans,sum);
for(int j=1;j<=t[i];j++)maxn[a[i][j]]=sum;
}
最后输出
AC代码
#include<bits/stdc++.h>
using namespace std;
int n,l,a[50001][250],t[50001],maxn[1000001],ans;
inline void init()
{
cin>>n>>l;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
for(int j=1;j*j<=x;j++)if(x%j==0)
{
if(j>=l)a[i][++t[i]]=j;
if(x/j>=l&&j*j!=x)a[i][++t[i]]=x/j;
}
}
}
inline void solve()
{
for(int i=1;i<=n;i++)
{
int sum=0;
for(int j=1;j<=t[i];j++)sum=max(sum,maxn[a[i][j]]+1);
ans=max(ans,sum);
for(int j=1;j<=t[i];j++)maxn[a[i][j]]=sum;
}
cout<<ans;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0),cout.tie(0);
init(),solve();
return 0;
}