51nod1056 最长等差数列 V2

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

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

随机化 hash 脑洞题

当N增长到5万,V1版本的双指针也怼不过去了。

然而既然题被出到OJ上,就一定有做它的方法(那可不一定.jpg)。

注意到只有ans>=200时才算有解,这说明如果有解,那么解对应的那些数分布是比较密集的(口胡)。

我们可以试着随机枚举两项,算出它们的公差,再分别向前向后找数,看能不能把等差数列续得更长。如果扫描每个数,留给随机化的时间就太少了,我们可以把数存进hash表里,这样就可以O(1)查询数是否存在,跑得飞快。

那么需要随机化多少次呢?本着不卡OJ白不卡的学术精神,我们从小到大倍增尝试。

随机1000次就能过第一个点

随机10000次能过两个点

随机100000次能过四个点

随机800000次能过八个点

随机8000000次能过一半点

随机16000000次只错三个点

随机32000000次就AC辣!

可喜可贺,可喜可贺

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 using namespace std;
 7 const int mxn=100007;
 8 int read(){
 9     int x=0,f=1;char ch=getchar();
10     while(ch<‘0‘ || ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
11     while(ch>=‘0‘ && ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
12     return x*f;
13 }
14 struct hstb{
15     int v,nxt;
16 }e[mxn];
17 int hd[mxn],mct=0;
18 void insert(int x){
19     int u=x%mxn;
20     for(int i=hd[u];i;i=e[i].nxt){
21         if(e[i].v==x)return;
22     }
23     e[++mct].v=x;e[mct].nxt=hd[u];hd[u]=mct;
24     return;
25 }
26 int find(int x){
27     int u=x%mxn;
28     for(int i=hd[u];i;i=e[i].nxt){
29         if(e[i].v==x)return 1;
30     }
31     return 0;
32 }
33 int n,a[mxn],b[mxn];
34 int ans=0;
35 int main(){
36     int i,j;
37     srand(19260817);
38     n=read();
39     for(i=1;i<=n;i++)a[i]=read(),b[i]=a[i];;
40     sort(a+1,a+n+1);
41     for(int i=1,cnt=0;i<=n;i++){
42         if(a[i]==a[i-1])cnt++;
43         else cnt=1;
44         ans=max(ans,cnt);
45     }
46     for(i=1;i<=n;i++) insert(a[i]);
47     random_shuffle(b+1,b+n+1);
48     int T=32000000;
49     while(T--){
50         int x=rand()%(n-1)+1,y=rand()%(n-1)+1;
51         x=b[x];y=b[y];if(x>y)swap(x,y);
52         if(x==y)continue;
53         int tmp=y-x;
54         int res=2;
55         for(i=y+tmp;i<=a[n];i+=tmp){
56             if(find(i)){
57                 res++;
58             }
59             else break;
60         }
61         for(i=x-tmp;i>=a[1];i-=tmp){
62             if(find(i)){
63                 res++;
64             }
65             else break;
66         }
67         ans=max(ans,res);
68     }
69     if(ans>=200)printf("%d\n",ans);
70     else printf("No Solution\n");
71     return 0;
72 }
时间: 2024-10-11 21:34:34

51nod1056 最长等差数列 V2的相关文章

51nod1055 最长等差数列

基准时间限制:2 秒 空间限制:262144 KB 分值: 80 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. Input 第1行:N,N为正整数的数量(3 <= N <= 10000). 第2 - N+1行:N个正整数.(2<= A[i] &

1055 最长等差数列

1055 最长等差数列 基准时间限制:2 秒 空间限制:262144 KB 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. Input 第1行:N,N为正整数的数量(3 <= N <= 10000). 第2 - N+1行:N个正整数.(2<= A

找最长等差数列的长度

题目描述:给定n(1<=n<=100)个数,从中找出尽可能多的数,使得他们能够组成一个等差数列.求最长的等差数列的长度,每个数的绝对值不超过10000000. 样例: 输入数组为:2,8,3,5,6,4 输出为:5 Java代码实现: 1 import java.util.*; 2 public class Main { 3 public static int maxlength(int a[]){ 4 int n=a.length; 5 int large=0; //记录最大长度 6 Arr

51 nod 1055 最长等差数列(dp)

1055 最长等差数列 基准时间限制:2 秒 空间限制:262144 KB 分值: 80 难度:5级算法题 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. Input 第1行:N,N为正整数的数量(3 <= N <= 10000). 第2 - N+1行

n个整数中,找出尽可能多的数使他们组成一个等差数列,求最长等差数列的长度

例子:  3,8,4,5,6,2          返回值应该为 :5 这是昨天做的一道优酷土豆的编程题,和leetcode中的128/ Longest Consecutive Sequence 有点相似,但是leetcode题的公差是确定的1,而这道题的公差是不确定的. 本人的写出的是一种通过穷举的方法实现查找最长等差数列,通过hash使查找更为方便,减少了复杂度. int calcAPLength(const vector<int> &intAr) // 找数列中,最长的等差数列的

leetcode 1027. 最长等差数列

题意:求最长等差序列的长度,数组长度是[0,2000],数值范围是[0,10000]. 思路:简单DP吧.dp[i][j]表示的是以第i个数结尾,差是j的最大长度. dp[i][A[i] - A[j]] = max(dp[i][A[i] - A[j]],dp[j][A[i]-A[j]]+1); 1 class Solution { 2 public: 3 int longestArithSeqLength(vector<int>& A) { 4 vector<unordered_

51nod 1055 最长等差数列

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1055 题意: 思路:先固定一个位置,然后从该中心点出发向两边扫,确实很难想到啊... 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<sta

算法10 最长等差序列问题

题目: 给定一个大小为n的数组,要求写出一个算法,求其最长的等差数列的子序列 分析: 该题需要分几种情况考虑. 1. 原数组是有序的,所要求的的子序列可以不连续. 对于数组arr[],不同的等差值d=1,2,3,4,5```(arr[max]-arr[min])可以求出不同的最长等差数列,然后在这些等差数列中求出最长的那个即可我们首先转化为求一个数组的固定等差值的最长等差子序列.如数组1,2,4,6,8,9,求等差值2的最长等差子序列为2,4,6,8 1.1 固定等差值的最长子序列 求符合条件的

BZOJ 3357: [Usaco2004]等差数列( dp )

dp(x, p) 表示序列中第x个数, 上一个数是p构成的等差数列的最长. 转移时从[1, x)中枚举p = seq[] 就行了.时间复杂度O(n²logn) --------------------------------------------------------------------------------- #include<bits/stdc++.h> #define rep(i, n) for(int i = 0; i < n; i++) #define Rep(i,