P4933 大师

1|0P4933 大师

1|1基础思路

  • 状态设置

    • Fk,i 表示公差为 ki 个电塔的等差数列数。
    • 两个 F 一个公差为 k,一个为 k
  • 状态转移

    • 对于Fk,i,从所有在 i 之前的的与第 i 个电塔差为 jF 方案加一转移而来。

    • for (int k = 0; k <= D; k++) { for (int i = 1; i <= n; i++) { for (int j = 1; j < i; j++) { if (h[i] - h[j] == k) { dp1[k][i] += dp1[k][j] + 1; dp1[k][i] = dp1[k][i] mod; } if (h[i] - h[j] == -k) { dp2[k][i] += dp2[k][j] + 1; dp2[k][i] = dp2[k][i] mod; } } if(k != 0) ans += dp1[k][i] + dp2[k][i], ans = ans mod; else ans += dp1[k][i], ans = ans mod; } }

然而只有65pts,毕竟接近 O(n3) 的复杂度。

1|2改进思路

我们可以把这个算法简化为,枚举一个公差 k,然后统计有多少个公差为 k 的等差数列。

枚举公差的时间复杂度是 O(v),观察数据范围可以猜测,统计的时间复杂度是,O(n),总复杂度是O(n×v)

回顾 65 分的那个的 DP,用到这个统计上来,用 Fki 表示以 i 结尾的,公差为 k 的等差数列有多少个,转移的时候枚举一个小于 ij ,然后当 hj=hik 时候从 Fk,j 转移到 Fk,i

状态已经不可能再简化了,但是转移可以。

我们发现,转移相当于一个求和,对小于 i 的所有高度等于hik 的位置的 DP 值求和。

我们可以维护一个数组 G 来记录这个和,这样转移就只有两行了。

Fk,i=Ghik

Ghi=Ghi+Fk,i

总复杂度是O(n×v)

1|3AC代码

#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #define mod %998244353 #define ll long long using namespace std; const int N = 1e3 + 10; const int M = 2e4 + 10; int n; int h[N]; ll dp1[M][N]; ll dp2[M][N]; ll G1[M]; ll G2[M]; ll ans = 0; int D = 0, minH = 0x7fffffff, maxH = 0; int main() { cin >> n; for (int i = 1; i <= n; i++) { cin >> h[i]; minH = min(minH, h[i]); maxH = max(maxH, h[i]); } D = maxH - minH; for (int k = 0; k <= D; k++) { memset(G1, 0, sizeof(G1)); memset(G2, 0, sizeof(G2)); for (int i = 1; i <= n; i++) { if (h[i] - k >= minH) dp1[k][i] = G1[h[i] - k]; if (h[i] + k <= maxH && k) dp2[k][i] = G2[h[i] + k]; G1[h[i]] += dp1[k][i] mod + 1, G1[h[i]] mod; G2[h[i]] += dp2[k][i] mod + 1, G2[h[i]] mod; ans += (dp1[k][i] mod + dp2[k][i] mod ) mod, ans mod; } } cout << (ans + n) mod; return 0; }

1|4实现上还有有一定难度的

  • 正确理解 G 数组的作用,无论是否能更新 dp1 都要更新 G 数组。
    • 因为该数组要记录在 i 之前的和,如果后面要用到,前面没更新就是错的。
  • 取模。
    • ans 和所有有关动规的数组都要开 long long 而且每一步都要取模。

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17832201.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(23)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示