跳转至

4月1日

2025-04-01 最近准备多做点DP。。。

总结

今日效率较低,白天看了笛卡尔树,洛谷模板题,顺便把杭州M补了,不咋难。

晚上只写了一道绿题。。然后现在是1点53,也是把那个P2679的补了。。

P5658这个,题单里说是树形DP,好好好,还是有一些需要理解的东西。明天接着做DP题单。。

洛谷P1095 普及/提高-

2025-04-01 tag: DP

黄题,但是还是做了四五十分钟。。。没啥好说的。

void ChatGptDeepSeek()
{
    int m, s, t;
    cin >> m >> s >> t;
    // 水题 枚举用了多少次魔法就行

    vector<int> d(t + 1), T(t + 1), r(t + 1), ned(t + 1);
    r[0] = m;               // 用 i 次魔法后 剩余的魔法
    T[0] = 0;               // 用 i 次魔法 恢复需要的时间
    ned[0] = (s + 16) / 17; // 用 i 次魔法 走到终点需要的时间

    d[0] = (t + 16) / 17 * 17; // 用 i 次魔法 t时间走的距离
    for (int i = 1; i <= t; i++)
    {
        T[i] = T[i - 1];
        r[i] = r[i - 1];
        if (r[i - 1] < 10)
        {
            T[i] += (10 - r[i - 1] + 3) / 4;
            r[i] = r[i] + (T[i] - T[i - 1]) * 4 - 10;
        }
        else
            r[i] -= 10;
        // 剩下 t-T[i]的时间 看能走多少
        ned[i] = T[i] + i;
        if (ned[i] > t)
            break;
        d[i] = i * 60 + (t - ned[i]) * 17;

        if (s >= i * 60)
        {
            ned[i] += (s - i * 60 + 16) / 17;
        }
        // cerr << i << " " << r[i] << " " << T[i] << " " << ned[i] << " \n";
    }
    int time = t + 1;
    for (int i = 0; i <= t; i++)
    {
        if (d[i] >= s && ned[i] <= t)
        {
            // cerr << i << " " << ned[i] << " \n";
            time = min(time, ned[i]);
        }
    }
    if (time != t + 1)
        cout << "Yes\n"
             << time << '\n';
    else
        cout << "No\n"
             << *max_element(d.begin(), d.end()) << '\n';
}

洛谷P2679 普及+/提高

2025-04-01 tag: DP

虽然想了一会,写了一个多小时。但这个就是很正常的DP题,挺好的。

学到一个小技巧,就是很多时候我们开多维的 DP 只会用到 \(i\)\(i-1\) 的,可以滚动数组,我一般喜欢每次循环新开一个。但是其实可以用 \(i\& 1\)\((i\&1) \oplus 1\) 这种表示,比较好写。

constexpr int mod = 1000000007;

int dp[2][202][202];
void ChatGptDeepSeek()
{
    int n, m, k;
    cin >> n >> m >> k;

    // 匹配了i长度,用了 j 段
    vector<char> A(n + 1), B(m + 1);
    for (int i = 1; i <= n; i++)
        cin >> A[i];
    for (int i = 1; i <= m; i++)
        cin >> B[i];
    vector<vector<int>> DP(m + 1, vector<int>(k + 1));
    dp[0][0][0] = DP[0][0] = 1;
    for (int i = 1; i <= n; i++)
    {

        vector nDP = DP;
        for (int j = 1; j <= min(i, m); j++)
        {
            if (A[i] == B[j])
            {
                for (int l = 1; l <= min(k, j); l++)
                {
                    dp[i & 1][j][l] = (dp[i & 1][j][l] + DP[j - 1][l - 1]) % mod;
                    nDP[j][l] = (nDP[j][l] + DP[j - 1][l - 1]) % mod;

                    dp[i & 1][j][l] = (dp[i & 1][j][l] + dp[(i ^ 1) & 1][j - 1][l]) % mod;
                    nDP[j][l] = (nDP[j][l] + dp[(i ^ 1) & 1][j - 1][l]) % mod;
                }
            }
        }
        for (int j = 0; j <= min(i, m); j++)
            for (int l = 1; l <= min(k, j); l++)
                dp[(i ^ 1) & 1][j][l] = 0;
        DP = nDP;
    }
    cout << DP[m][k] << '\n';
}

洛谷P5658 普及+/提高

2025-04-01 tag: DFS

我服了,本来是在写 DP题单的,WA了一晚上,不是哥们这跟DP有关系吗?虽然应该可以,但是会很不好做。

学习了题解的方法。。。

void ChatGptDeepSeek()
{
    int n;
    cin >> n;
    string s;
    cin >> s;
    vector<vector<ll>> adj(n + 1, vector<ll>());
    vector<int> fa(n + 1);
    for (int i = 2; i <= n; i++)
    {
        int x;
        cin >> x;
        fa[i] = x;
        adj[x].push_back(i);
    }
    s = " " + s;
    vector<int> stk, lst(n + 1);
    vector<long long> sum(n + 1);

    auto dfs = [&](auto &&self, int u, int pre) -> void
    {
        int tmp = 0;
        if (s[u] == ')')
        {
            if (!stk.empty())
            {
                tmp = stk.back();
                stk.pop_back();
                lst[u] = lst[fa[tmp]] + 1;
            }
        }
        else
            stk.push_back(u);
        sum[u] = sum[pre] + lst[u];
        for (auto v : adj[u])
        {
            if (v == pre)
                continue;
            self(self, v, u);
        }
        if (tmp)
            stk.push_back(tmp);
        else if (!stk.empty())
            stk.pop_back();
    };
    dfs(dfs, 1, 0);
    long long ans = 0;
    for (int i = 1; i <= n; i++)
    {
        ans ^= (1LL * i * sum[i]);
    }
    cout << ans << '\n';
}