這個和1055那個題差不多,稍微改改就過了,首先是剪枝的改寫,這個剪枝是必過的,唐老師在討論裡進行了證明。
首先要明確等差數列的定義。
乙個等差數列可以用首項、公差和項數的三元組 (
firs
t,de
lta,
leng
th)
表示,當然這個 f
irst
也可以換成末項 l
ast
,取決於你的演算法。
我們要考慮的等差數列要盡量用少的資訊表示所有的可能,也就是說提取出來的等差數列之間不能有相互包含的關係,例如 (
2,3,
4)和 (
2,3,
5)就冗餘了,而 (
2,3,
4)和 (
5,3,
4)也是冗餘的,因為當它們出現在同乙個序列裡時, (
2,3,
5)也是存在的。
因此我們只需要考慮滿足 (
firs
t−de
lta)
這個數字不存在,並且 (
last
+del
ta)
這個數字不存在的等差數列。
接下來要發現這樣的等差數列在 k
充分大時是不多的。
定義:集合裡的兩個元素是足夠相鄰的,當且僅當它們的排名之差不超過 n
k−1
。由鴿巢原理可知,乙個長度為 k
的等差數列必然包含至少 k
−12
對足夠相鄰的元素(考慮等差數列裡排名最小的和排名最大的那兩個元素)。
而集合裡足夠相鄰的元素對數不超過 n
22(k
−1)
,我們所求的不同等差數列也不會包含相同的一對足夠相鄰的元素,所以我們能得到的等差數列數量是不超過 n
2(k−
1)2
的。最後要利用這個性質來構造相應的演算法。
利用數量不多的性質,我們可以嘗試找出所有長度至少為 200 的等差數列,從中選取最長的那個。
注意到上面的證明利用到了集合的大小,類似地也可以證明,這樣的等差數列必然有 ⌊
k2⌋
項在前 ⌊
n2⌋
小的元素集合裡,或者有 ⌊
k2⌋
項在前 ⌈
n2⌉
大的元素集合裡。
而集合大小減半同時數列項數減半對數列數量的影響是不大的,所以可以嘗試對集合分治,分別找出更小情況的解,然後放到大的集合裡嘗試向左向右 o
(k)
擴張,再進行去重,從而得到當前情況的解。
不妨設 t
(n,k
)
表示從大小為 n
的集合裡提取長度至少為 k
的不同等差數列的複雜度,則有 t
(n,k
)=2t
(n2,
k2)+
o(n2
k2k)
⇒t(n
,k)=
o(n2
klognk
)
。其次,就是hash這個hash要手打,hash就是把之前的dp陣列給換掉。暴力的去查詢。最後,我想說的是,花了130個點頭盾,以為能上第一,誰知道上了第二。**還是發了吧。。。。
#include#include#define ll long long
using namespace std;
const int mod=233333;
int a[50010],ha[mod],ans=199,last[50010],n;
int read()
void add(int k,int i)
bool find1(int k)
int main()}}
//cout<=200)
printf("%d\n",ans);
else printf("no solution\n");
return 0;
}
51nod1056 最長等差數列 V2
1056 最長等差數列 v2 基準時間限制 8 秒 空間限制 131072 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...
51Nod 最長等差數列
題目描述 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。輸...
51nod 1055 最長等差數列
原題鏈結 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...