https://codeforces.com/gym/102082
题意:给你一个序列,从中选若干个元素,使这些元素可以组成一个等差序列,求这个等差序列长度的最大值。
分析:对于每个a[i]可以枚举以它为结尾的不同公差的序列,因为a[i]的范围很大,所以直接用等差数列的倒数第二项下标j来表示公差,那么dp[i][j]表示以i为结尾,j为倒数第二项,公差是a[i]-a[j]的最长序列。然后二分找倒数第三项转移状态即可。
#include "bits/stdc++.h"
namespace fastIO {
#define BUF_SIZE 100000
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if (p1 == pend) {
p1 = buf;
pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if (pend == p1) {
IOerror = 1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
inline void read(int &x) {
char ch;
while (blank(ch = nc()));
if (IOerror) return;
for (x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0');
}
#undef BUF_SIZE
};
using namespace fastIO;
using namespace std;
const int mod = 1e9 + 7;
int n;
int a[5004];
unordered_map<int, int> mp;
int dp[5004][5004];
int cnt = 0;
int main() {
read(n);
for (int i = 1; i <= n; ++i) {
read(a[i]);
}
sort(a + 1, a + 1 + n);
memset(dp, 0, sizeof(dp));
int ans = 0;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j < i; ++j) {
int d = a[i] - a[j];
int pos = lower_bound(a + 1, a + 1 + n, a[j] - d) - a;
if (pos < n + 1 && a[pos] == a[j] - d) {
dp[i][j] = dp[j][pos] + 1;
ans = max(ans, dp[i][j]);
} else {
dp[i][j] = 2;
ans = max(ans, dp[i][j]);
}
}
}
cout << ans << endl;
}