5·17总结

第一题:P1115 最大子段和

思路
使用动态规划,dp[i] 表示以 a[i] 结尾的最大子段和。状态转移方程为 dp[i] = max(a[i], dp[i-1] + a[i])。遍历所有可能的子段结尾,取最大值即为答案。

重难点

  • 正确设计状态转移方程,确保包含所有可能的子段情况。
  • 处理全负数情况,需初始化答案为极小值。

正确代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5, inf=1e18;
int n, a[maxn], dp[maxn], ans=-inf;

int main() {
    cin >> n;
    for(int i=1; i<=n; i++) cin >> a[i];
    dp[1] = a[1];
    for(int i=2; i<=n; i++) 
        dp[i] = max(a[i], dp[i-1] + a[i]);
    for(int i=1; i<=n; i++) 
        ans = max(ans, dp[i]);
    cout << ans;
    return 0;
}

第二题:B3637 最长上升子序列

思路
动态规划求解。dp[i] 表示以 a[i] 结尾的最长上升子序列长度。遍历所有 j < i,若 a[j] < a[i],则更新 dp[i] = max(dp[i], dp[j]+1)

重难点

  • 理解状态定义和转移逻辑。
  • O(n²) 复杂度适用于题目数据范围。

正确代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e3+5;
int n, a[maxn], dp[maxn], ans;

int main() {
    cin >> n;
    for(int i=1; i<=n; i++) cin >> a[i];
    for(int i=1; i<=n; i++) {
        dp[i] = 1;
        for(int j=1; j<i; j++) 
            if(a[j] < a[i]) 
                dp[i] = max(dp[i], dp[j]+1);
        ans = max(ans, dp[i]);
    }
    cout << ans;
    return 0;
}

第三题:U554326 整除-基础

思路
动态规划。dp[i][j] 表示长度为 i 的序列,末尾为 j 的方案数。初始化 dp[1][j] = 1,遍历所有可能的相邻元素,若满足整除条件则转移。

重难点

  • 处理状态转移的条件(整除或反向整除)。
  • O(nk²) 复杂度需合理控制循环结构。

正确代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=105, mod=99824353;
int n, k, dp[maxn][maxn];

int main() {
    cin >> n >> k;
    for(int i=1; i<=k; i++) dp[1][i] = 1;
    for(int i=2; i<=n; i++) 
        for(int j=1; j<=k; j++) 
            for(int l=1; l<=k; l++) 
                if(j%l == 0 || l%j == 0) 
                    dp[i][l] = (dp[i][l] + dp[i-1][j]) % mod;
    int ans = 0;
    for(int i=1; i<=k; i++) 
        ans = (ans + dp[n][i]) % mod;
    cout << ans;
    return 0;
}

第四题:U554323 整除运算-基础

思路
类似第三题,但转移条件为:前一个元素 j 需满足 j <= lj % l != 0。动态规划状态转移时检查条件。

重难点

  • 正确理解题目条件(A≤B 或 A%B≠0)。
  • 确保转移条件逻辑正确。

正确代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1005, mod=99824353;
int n, k, dp[maxn][maxn];

int main() {
    cin >> n >> k;
    for(int i=1; i<=k; i++) dp[1][i] = 1;
    for(int i=2; i<=n; i++) 
        for(int j=1; j<=k; j++) 
            for(int l=1; l<=k; l++) 
                if(j <= l || j % l != 0) 
                    dp[i][l] = (dp[i][l] + dp[i-1][j]) % mod;
    int ans = 0;
    for(int i=1; i<=k; i++) 
        ans = (ans + dp[n][i]) % mod;
    cout << ans;
    return 0;
}
posted @ 2025-05-23 19:56  KK_SpongeBob  阅读(15)  评论(0)    收藏  举报