题意:给你n个数,让你找最长的等差数列。
Solution
想了好久,突然想出了一个非常妙的做法。
首先用hash来记录每一个数(下标)。
然后暴力枚举等差数列的第一项和第二项,假设两个数分别为
x
,
y
x,y
x,y,判断如果
2
∗
x
−
y
2*x-y
2∗x−y存在,就说明这个等差数列已经被找过,就不用管了,如果没有就暴力跳着找,输出的时候再跳一次就好了。
Code
#include<bits/stdc++.h>
#define ll long long
#define gc getchar
#define pc putchar
#define pii pair<int,int>
#define mp make_pair
#define fi first
#define se second
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define dwn(i,x,y) for(int i=x;i>=y;i--)
using namespace std;
template<typename T>inline void qr(T &x){
x=0;int f=0;char s=gc();
while(s<'0'||'9'<s)f|=s=='-',s=gc();
while('0'<=s&&s<='9')x=x*10+s-48,s=gc();
x=f?-x:x;
}
int cc=0,buf[31];
template<typename T>inline void qw(T x){
if(x<0)putchar('-'),x=-x;
do{buf[++cc]=int(x%10);x/=10;}while(x);
while(cc)pc(buf[cc--]+'0');
}
const int N=1e4+10,mod=501197;
int n,tot,hd[mod],p[N],nxt[N];pii a[N];
void ins(int id){
int x=a[id].fi%mod;
for(int i=hd[x];i;i=nxt[i])if(a[p[i]].fi==a[id].fi)return;
p[++tot]=id,nxt[tot]=hd[x],hd[x]=tot;
}
int query(int num){
if(num<=0||num>1e9)return 0;
int x=num%mod;
for(int i=hd[x];i;i=nxt[i])if(a[p[i]].fi==num)return a[p[i]].se;
return 0;
}
int main(){
int tt;qr(tt);
rep(i,1,tt)qr(a[i].fi),a[i].se=i;
sort(a+1,a+tt+1);
rep(i,1,tt)if(a[i].fi!=a[i-1].fi){a[++n]=a[i];ins(n);}
if(n==1){puts("1\n1");return 0;}
int ans=0;pii pos;
rep(i,1,n)
rep(j,i+1,n)if(!query(2*a[i].fi-a[j].fi)){
int now=2;tt=a[j].fi-a[i].fi;
for(int k=a[j].fi+tt;;k+=tt){
if(query(k))now++;
else break;
}
if(now>ans)ans=now,pos=mp(i,j);
}
qw(ans);puts("");
qw(a[pos.fi].se),pc(' '),qw(a[pos.se].se),pc(' ');
tt=a[pos.se].fi-a[pos.fi].fi;
for(int i=a[pos.se].fi+tt;;i+=tt){
int now=query(i);
if(!now)break;
qw(now),pc(' ');
}
return 0;
}