1056 最长等差数列 V2

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
#include
#include
#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]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*ybreak;
            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;
}

你可能感兴趣的:(暴力,水题,乱搞)