原题传送门
使用DP
从
h
z
w
e
r
hzwer
hzwer看来的
d
p
[
i
]
dp[i]
dp[i]表示到第i个数并且选了这个数的答案
转移方程:
d
p
[
i
]
=
m
a
x
(
d
p
[
l
a
s
t
[
x
]
]
)
,
x
∣
a
[
i
]
且
x
>
=
L
dp[i]=max(dp[last[x]]),x|a[i] 且x >= L
dp[i]=max(dp[last[x]]),x∣a[i]且x>=L
l
a
s
t
[
x
]
=
m
a
x
(
j
)
,
j
<
i
last[x]=max(j),j<i
last[x]=max(j),j<i
last数组的意义就是把每个数在第i个数前面最后出现的位置记录下来
因为枚举的是每个数的因数,所以复杂度根号级别
时间复杂度
O
(
n
a
)
O(n\sqrt{a})
O(na)
Code:
#include <bits/stdc++.h>
#define maxn 50010
#define maxm 1000010
using namespace std;
int n, L, ans, dp[maxn], last[maxm];
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
int main(){
n = read(), L = read();
for (int i = 1; i <= n; ++i){
int x = read();
for (int j = 1; j * j <= x; ++j){
if (x % j) continue;
if (j >= L) dp[i] = max(dp[i], dp[last[j]] + 1);
if (x / j >= L) dp[i] = max(dp[i], dp[last[x / j]] + 1);
last[j] = last[x / j] = i;
}
ans = max(ans, dp[i]);
}
printf("%d\n", ans);
return 0;
}