题目:
分析:
(自己瞎yy的DP方程竟然1A了,写篇博客庆祝一下)
(以及特斯拉电塔是向Red Alert致敬吗233)
这里只讨论公差不小于 0 0 0的情况,小于 0 0 0的情况进行复读机即可(注意不要重复计算公差为 0 0 0的情况)。
用 d p [ i ] [ j ] dp[i][j] dp[i][j]表示结尾为第 i i i个数,公差为 j j j的长度不小于 2 2 2的非降等差数列的方案数(单独 1 1 1个数的情况公差不确定不好处理,最后给答案加上 n n n就行了)。
那么对于
i
i
i,枚举所有
j
(
j
<
i
j(j<i
j(j<i且
h
[
j
]
≤
h
[
i
]
)
h[j]\leq h[i])
h[j]≤h[i]),则有
(加
1
1
1是加上了新的长度为
2
2
2的数列
{
h
[
j
]
,
h
[
i
]
}
\{h[j],h[i]\}
{h[j],h[i]})
d p [ i ] [ h [ i ] − h [ j ] ] = ∑ j ( d p [ j ] [ h [ i ] − h [ j ] ] + 1 ) dp[i][h[i]-h[j]]=\sum_j (dp[j][h[i]-h[j]]+1) dp[i][h[i]−h[j]]=j∑(dp[j][h[i]−h[j]]+1)
总的来说还是一道比较基础的DP题。时间复杂度 O ( n V ) O(nV) O(nV)
代码:
先念诗:
瓜之嘴
作者:YYC神犇
好山配好水,
好瓜配好嘴。
不膜神仙瓜,
写题一定萎。
(1A多亏模数叫Jumpmelon)
#include <cstdio>
#include <algorithm>
#include <iostream>
#include <cstring>
using namespace std;
namespace zyt
{
typedef long long ll;
const int N = 1010, V = 2e4 + 10, Jumpmelon = 998244353;
int h[N], n, dp[N][V], ans;
int work()
{
cin >> n;
for (int i = 1; i <= n; i++)
cin >> h[i];
for (int i = 1; i <= n; i++)//upper
{
for (int j = 1; j < i; j++)
if (h[j] <= h[i])
dp[i][h[i] - h[j]] = (dp[i][h[i] - h[j]] + dp[j][h[i] - h[j]] + 1) % Jumpmelon;
}
for (int i = 1; i <= n; i++)
for (int j = 0; j < V; j++)
ans = (ans + dp[i][j]) % Jumpmelon;
memset(dp, 0, sizeof(dp));
for (int i = 1; i <= n; i++)//lower
{
for (int j = 1; j < i; j++)
if (h[i] < h[j])
dp[i][h[j] - h[i]] = (dp[i][h[j] - h[i]] + dp[j][h[j] - h[i]] + 1) % Jumpmelon;
}
for (int i = 1; i <= n; i++)
for (int j = 0; j < V; j++)
ans = (ans + dp[i][j]) % Jumpmelon;
cout << (ans + n) % Jumpmelon;
return 0;
}
}
int main()
{
return zyt::work();
}