Problem Description
众所周知,度度熊喜欢的字符只有两个:B 和D。
今天,它发明了一个游戏:D游戏。
度度熊的英文并不是很高明,所以这里的D,没什么高深的含义,只是代指等差数列[(等差数列百科)](http://baike.baidu.com/view/62268.htm)中的公差D。
这个游戏是这样的,首先度度熊拥有一个公差集合 {D} ,然后它依次写下 N 个数字排成一行。游戏规则很简单:
1. 在当前剩下的有序数组中选择 X(X≥2) 个连续数字;
2. 检查 1 选择的 X 个数字是否构成等差数列,且公差 d∈{D} ;
3. 如果 2 满足,可以在数组中删除这 X 个数字;
4. 重复 1−3 步,直到无法删除更多数字。
度度熊最多能删掉多少个数字,如果它足够聪明的话?
今天,它发明了一个游戏:D游戏。
度度熊的英文并不是很高明,所以这里的D,没什么高深的含义,只是代指等差数列[(等差数列百科)](http://baike.baidu.com/view/62268.htm)中的公差D。
这个游戏是这样的,首先度度熊拥有一个公差集合 {D} ,然后它依次写下 N 个数字排成一行。游戏规则很简单:
1. 在当前剩下的有序数组中选择 X(X≥2) 个连续数字;
2. 检查 1 选择的 X 个数字是否构成等差数列,且公差 d∈{D} ;
3. 如果 2 满足,可以在数组中删除这 X 个数字;
4. 重复 1−3 步,直到无法删除更多数字。
度度熊最多能删掉多少个数字,如果它足够聪明的话?
Input
第一行一个整数
T
,表示
T(1≤T≤100)
组数据。
每组数据以两个整数 N , M 开始 。接着的一行包括 N 个整数,表示排成一行的有序数组 Ai 。接下来的一行是 M 个整数,即给定的公差集合 Di 。
1≤N,M≤300
−1 000 000 000≤Ai,Di≤1 000 000 000
每组数据以两个整数 N , M 开始 。接着的一行包括 N 个整数,表示排成一行的有序数组 Ai 。接下来的一行是 M 个整数,即给定的公差集合 Di 。
1≤N,M≤300
−1 000 000 000≤Ai,Di≤1 000 000 000
Output
对于每组数据,输出最多能删掉的数字 。
Sample Input
3 3 1 1 2 3 1 3 2 1 2 4 1 2 4 2 1 3 4 3 1 2
Sample Output
3 2 4也算不上是多难的题目,理解题意以后就差不多能想到这样的方案,因为每次选的数必须是连续的,并且是等差数列,事实上,对于等差数列只要考虑拿两个和三个的情况,更多的一定可以拆成2和3的和的情况。那么只要n^3枚举就可以了。#pragma comment(linker, "/STACK:1024000000,1024000000") #include<map> #include<set> #include<queue> #include<stack> #include<cmath> #include<cstdio> #include<bitset> #include<string> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #include<functional> using namespace std; typedef __int64 LL; const int low(int x) { return x&-x; } const int INF = 0x7FFFFFFF; const int mod = 1e9 + 7; const int maxn = 3e2 + 10; int T, n, m, a[maxn], d[maxn], x; map<int, bool> M; int f[maxn][maxn], dp[maxn]; int main() { scanf("%d", &T); while (T--) { scanf("%d%d", &n, &m); M.clear(); memset(f, 0, sizeof(f)); memset(dp, 0, sizeof(dp)); for (int i = 1; i <= n; i++) scanf("%d", &a[i]), f[i][i - 1] = 1; for (int i = 0; i < m; i++) scanf("%d", &x), M[x] = true; for (int i = 1; i <= n; i++) { for (int j = 1; j + i <= n; j++) { if (M[a[j + i] - a[j]]) f[j][j + i] |= f[j + 1][j + i - 1]; for (int k = 1; k < i; k++) f[j][j + i] |= f[j][j + k] && f[j + k + 1][j + i]; if ((a[j + i] - a[j]) % 2 == 0 && M[(a[j + i] - a[j]) / 2]) { for (int k = 1; k < i; k++) { if (a[j + k] + a[j + k] == a[j + i] + a[j]) { f[j][j + i] |= f[j + 1][j + k - 1] && f[j + k + 1][j + i - 1]; } } } } } for (int i = 1; i <= n; i++) { dp[i] = dp[i - 1]; for (int j = 1; j <= i; j++) { if (!f[j][i]) continue; dp[i] = max(dp[i], dp[j - 1] + i - j + 1); } } printf("%d\n", dp[n]); } return 0; }