显然可以发现,构造出的等差数列,至少包含原数列的其中一项。
那么可以先枚举一个固定的公差,枚举原数列的其中几项,来构造等差数列。但是要枚举哪几项呢?随机枚举!!!
在比赛中我枚举了 \(7\sqrt n\) 项A了,但如果要保证正确性应该差不多 \(20\sqrt n\)。
复杂度分析:从 \(0\sim \dfrac{w}{n-1}\) 枚举公差,再枚举 \(\sqrt n\) 项然后 \(\mathcal O(n)\) 计算答案,应为 \(\mathcal O(\dfrac{w}{n}\times n\sqrt n)=\mathcal O(w\sqrt n)\),足以通过此题。
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define ll long long
#define TT template<typename T>
namespace io{...}using namespace io;
const int N=3e5+5;
int n,w,a[N],ans=N;
int main(){
srand(19491001);
n=read();w=read();
int tot=sqrt(n)*20;
if(n<=2)return puts("0"),0;
for(int i=1;i<=n;i++)
a[i]=read();
for(int d=0;d<=3e5;d++){
if(1ll*d*(n-1)>=1ll*w)break;//当极差大于w
for(int t=1;t<=tot;t++){
int p=rand()%n+1,res=0;
ll st=a[p]-1ll*(p-1)*d,ed=a[p]+1ll*(n-p)*d;//计算首末项
if(st<=0||ed>w)continue;
for(int i=1;i<p;i++,st+=d)
if(a[i]!=st)res++;
for(int i=n;i>p;i--,ed-=d)
if(a[i]!=ed)res++;
//计算答案
ans=min(ans,res);
}
}writeln(ans);
return 0;
}
比赛唯一过掉的题QAQ
原文:https://www.cnblogs.com/aday526/p/solution-p7273.html