Arithmetic Progressions
Problem Description
An arithmetic progression is a sequence of numbers a1,a2,...,aka_1, a_2, . . . , a_ka1,a2,...,ak where the difference of consec- utive members ai+1 − ai is a constant (1 ≤ i ≤ k − 1). For example, the sequence 5, 8, 11, 14, 17 is an arithmetic progression of length 5 with the common difference 3.
In this problem, you are requested to find the longest arithmetic progression which can be formed selecting some numbers from a given set of numbers. For example, if the given set of numbers
is {0, 1, 3, 5, 6, 9}, you can form arithmetic progressions such as 0, 3, 6, 9 with the common
difference 3, or 9, 5, 1 with the common difference −4. In this case, the progressions 0, 3, 6, 9
and 9, 6, 3, 0 are the longest.
Input
The input consists of a single test case of the following format.
nnn
n is the number of elements of the set, which is an integer satisfying 2 ≤ n ≤ 5000. Each v_i (1 ≤ i ≤ n) is an element of the set, which is an integer satisfying 0 ≤ v_i ≤ 10^9. v_i’s are all different, i.e., v_i ≠ v_j if i ≠ j.
Output
Output the length of the longest arithmetic progressions which can be formed selecting some numbers from the given set of numbers.
Sample Input
6
0 1 3 5 6 9
Sample Output
4
Sample Input2
7
1 4 7 3 2 6 5
Sample Output2
7
Sample Input3
5
1 2 4 8 16
Sample Output3
2
Brief Description
找最长上升等差数列
Solution:
一开始写了个大常数n方的算法,时间给的是5秒(没有给java额外的时间。。。)
中间用了HashMap, TLE了,这让我对HashMap非常失望,所谓的O(1)并没有想象中的块
(n只有1e5)
TLE 核心代码:
for (int i = 1; i <= n; ++i) {
for (int j = 1; j < i; ++j) {
int gc = a[j] - a[i];
int len = getLen(j, gc);
gcToLen[i].put(gc, len + 1);
ans = Math.max(ans, len + 1);
}
}
没办法,只能dp了,搞了大半天。。。
dp(i,j)表示从第一个到第j个的序列中,以a[i],a[j]的差为公差的最长等差数列,可以很容易的转移
复杂度
O
(
n
2
)
O(n^2)
O(n2)
AC Code:
#include <bits/stdc++.h>
#define si(a) scanf("%d", &a)
#define sii(a, b) scanf("%d", &a, &b)
#define siii(a, b, c) scanf("%d", &a, &c)
#define siiii(a, b, c, d) scanf("%d", &a, &c, &d)
#define pi(a) printf("%d\n", a)
#define pii(a, b) printf("%d %d\n", a, b)
#define piii(a, b, c) printf("%d %d% d\n", a, b, c)
#define piiii(a, b, c, d) printf("%d %d %d %d\n", a, b, c, d)
#define forRange(i, j, k) for(int i = j; i < k; ++i)
#define mem(a, b) memset(a, b, sizeof(a))
#define printArrInRange(a, from, to) for(int i = from; i < to; ++i) printf("%d ", a[i]); putchar('\n')
#define printArr(a) putchar('['); for(auto k : a) printf("%d ", k); putchar(']'); putchar('\n')
#define mCopy(to, from) memcpy(to, from, sizeof(from))
#define testData(f) freopen(f,"r",stdin)
using namespace std;
int const MAXN = 5005;
int a[MAXN];
int dp[MAXN][MAXN];
int main() {
int n, ans;
si(n);
if (n == 1) {
puts("1");
return 0;
}
for (int i = 0; i < n; i++)
si(a[i]);
sort(a, a + n);
for (int i = 0; i < n; i++)
for (int j = i + 1; j < n; ++j)
dp[i][j] = 2;
ans = 2;
for (int i = 1; i < n - 1; ++i) {
int leftPos = i - 1;
int rightPos = i + 1;
while (leftPos > -1 && rightPos < n) {
int leftGap = a[i] - a[leftPos];
int rightGap = a[rightPos] - a[i];
if (leftGap < rightGap)
leftPos--;
else if (leftGap > rightGap)
rightPos++;
else {
dp[i][rightPos] = dp[leftPos][i] + 1;
ans = max(ans, dp[i][rightPos]);
--leftPos;
++rightPos;
}
}
}
printf("%d", ans);
return 0;
}