您的位置:首页 > 其它

1056 最长等差数列 V2

2017-09-25 16:41 197 查看

1056 最长等差数列 V2

基准时间限制:8 秒 空间限制:131072 KB

Description

N个不同的正整数,从中选出一些数组成等差数列。

例如:1 3 5 6 8 9 10 12 13 14

等差子数列包括(仅包括两项的不列举)

1 3 5

1 5 9 13

3 6 9 12

3 8 13

5 9 13

6 8 10 12 14

其中6 8 10 12 14最长,长度为5。

现在给出N个数,你来从中找出一个长度 >= 200 的等差数列,如果没有,输出No Solution,如果存在多个,输出最长的那个的长度。

Input

第1行:N,N为正整数的数量(1000 <= N <= 50000)。

第2 - N+1行:N个正整数。(2<= A[i] <= 10^9)

(注,真实数据中N >= 1000,输入范例并不符合这个条件,只是一个输入格式的描述)

Output

找出一个长度 >= 200 的等差数列,如果没有,输出No Solution,如果存在多个,输出最长的那个的长度。

Input示例

10

1

3

5

6

8

9

10

12

13

14

Output示例

No Solution

Solution

显然这道题不能用常规方法n^3,虽说时间复杂度有8s,但n^3还是会炸,首先,通过枚举两个数确定公差是必须的,所以说n^2一定存在,而对于判断这个数列的长度,则可以采取hash的玄学优化,虽然看似这样还是n^3的,不过却可以跑得飞快(当然你也可以加个排序来剪枝)

#include<cstdio>
#include<algorithm>
#include<cmath>
#define inf 1000000000
#define Mod 10000000
using namespace std;
int mx,mn,ans=0,n;
int x[50010],hash[Mod];
int read(){
int ans=0;
char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9')ans=ans*10+ch-'0',ch=getchar();
return ans;
}
int calc(int x){
int now=x%Mod;
if (!now) now+=Mod;
while (hash[now]!=0 && hash[now]!=x) now=now%Mod+1;
return now;
}
bool find(int x){
if (hash[calc(x)]==x) return 1;
return 0;
}
int main(){
mx=0,mn=inf;
n=read();
for (int i=1;i<=n;i++){
x[i]=read();
if (x[i]>mx) mx=x[i];
if (x[i]<mn) mn=x[i];
}
ans=199;
sort(x+1,x+n+1);
x[0]=x[1]-1;
for (int i=1;i<=n;i++)
hash[calc(x[i])]=x[i];
for (int i=1;i<=n;i++)
for (int j=i+1;j<=n;j++){
int y=x[j]-x[i],k=x[j],len=2;;
if ((long long)x[i]+ans*y>mx || (long long)x[i]+ans*y<mn) break;
while (1){
if (!find(k+y)) break;
k+=y;
len++;
}
if (len>ans) ans=len;
}
if (ans<200) printf("No Solution"); else printf("%d\n",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  程序设计