AtCoder Beginner Contest 362 补题记录(A~E,G)

A

分三类情况讨论即可。

void solveqwq() {
    int r = io.read(), g = io.read(), b = io.read();
    string qwq = io.readstring();
    if (qwq == "Blue") printf("%lld\n", min(r, g));
    else if (qwq == "Red") printf("%lld\n", min(g, b));
    else printf("%lld\n", min(r, b));
}

B

求出三角形三条边然后暴力判断即可。

void solveqwq() {
    int xa = io.read(), ya = io.read(), xb = io.read(), yb = io.read(), xc = io.read(), yc = io.read();
    int AB = (xa - xb) * (xa - xb) + (ya - yb) * (ya - yb);
    int AC = (xa - xc) * (xa - xc) + (ya - yc) * (ya - yc);
    int BC = (xb - xc) * (xb - xc) + (yb - yc) * (yb - yc);
    int a[3] = {AB, AC, BC}; sort(a, a + 3);
    if (a[0] + a[1] == a[2]) puts("Yes");
    else puts("No");
}

C

唯一一道不是原题且有意义的题

首先这个构造可以构造出来的和一定在范围 [L,R] 中。然后考虑开两个前缀和分别记录左端点和右端点的和。

此时枚举每一个区间,分两种情况讨论:

  • 此时取 Li 的值仍然可行。则继续贪心取 Li。这个(可行)可以通过刚刚预处理出的前缀和来计算。
  • 此时取 Li 的值仍然不可行。直接套公式计算出最小可行的值,然后剩下的值全部选取 Ri 即可。

时间复杂度为 O(n)

void solveqwq() {
    int n = io.read();
    for (int i = 1; i <= n; ++i) l[i] = io.read(), r[i] = io.read();
    int minv = 0, maxv = 0;
    for (int i = 1; i <= n; ++i) minv += l[i], maxv += r[i];
    if (minv > 0 || maxv < 0) puts("No");
    else {
        puts("Yes");
        for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + r[i], qwq[i] = qwq[i - 1] + l[i];
        vector<int> res;
        for (int i = 1; i <= n; ++i) {
            int tmp = qwq[i - 1] + sum[n] - sum[i] + l[i];
            if (tmp >= 0) res.emplace_back(l[i]);
            else {
                res.emplace_back(l[i] - tmp);
                for (int j = i + 1; j <= n; ++j) res.emplace_back(r[j]);
                break;
            }
        }
        for (auto &val : res) printf("%lld ", val);
        puts("");
    }
}

D

《模板:单源最短路径》

代码不贴了。

E

fi,j,k 为当前选取的最后一个元素为 i,选取了 j 个元素,等差数列的公差为 k 的方案数。

则可以枚举 ijk 和上一个选择的元素 p,然后有转移方程 fi,j,kfp,j1,k

for (int i = 3; i <= n; ++i)
	for (int j = 3; j <= i; ++j)
		for (int k = 1; k <= idx; ++k)
			for (int p = j - 1; p < i; ++p)
				if (chg[k] == a[p] - a[i])
					f[i][j][k] = (f[i][j][k] + f[p][j - 1][k]) % mod;

但是时间复杂度为 O(n5),会超时。

因此考虑优化。因为没人想要优化状态所以考虑优化枚举上一个选择元素 p 的过程。容易发现一个合法的 p 关于三元组 (i,j,k) 而言,需要满足 k=aiap。因此考虑直接给所有符合这样元素的条件存储下来。具体的说:

gj,k,p 表示选取 j 个元素,目前公差为 k,且上一个元素值为 p 的方案数。

于是可以在枚举 f 的转移的时候一并转移上 g。此时 g 的转移为:gj,k,aifi,j,k

因此 f 的转移也可以通过 g 来优化,即为:fi,j,kgj1,k,ai+k

然后此时你需要在转移的过程中插入 j=2 的初始条件。因为 j2 的时候任意一个 j 元组都符合条件,所以说 j=1 时答案为 nj=2 时答案为 (n2)

然后因为 ai109 所以你还需要对所有的元素离散化。但是因为目前时间复杂度为 O(n4) 再多一只 log 都是致命打击所以说你可能需要一些【】来离散化,然后这样以来 dp 的方程变成了依托【】,代码就十分混乱。

还有就是【】在写这个题的时候忘记修改输入文件为 E 题样例,然后用 D 题样例虚空调试 1h。警钟砸碎。

void solveqwq() {
    // freopen(".out", "w", stdout);
    int n = io.read();
    for (int i = 1; i <= n; ++i) a[i] = io.read();
    if (n <= 2) {
        if (n == 1) printf("%lld\n", n);
        else printf("%lld %lld\n", n, n * (n - 1) / 2);
    } else {
        vector<int> vec;
        for (int i = 1; i <= n; ++i)
            for (int j = i + 1; j <= n; ++j)
                vec.emplace_back(a[i] - a[j]);
        sort(vec.begin(), vec.end());
        vec.erase(unique(vec.begin(), vec.end()), vec.end());
        unordered_map<int, int> mp, __;
        int idx = 0;
        for (auto &val : vec) mp[val] = ++idx, tru[idx] = val;
        set<int> se;
        for (int i = 1; i <= n; ++i)
            se.insert(a[i]), b[i] = a[i];
        int idxx = 0;
        for (auto &val : se) __[val] = ++idxx, rid[idxx] = val;
        // f[i][j][k] 表示当前最后一个元素是 i 选取了 j 个元素 差为 k 的方案数
        // g[j][k][p] 表示选取 j 个元素差为 k 上一个元素值为 p 的方案数
        for (int i = 2; i <= n; ++i) {
            for (int j = i; j >= 3; j--) {
                for (int k = 1; k <= idx; ++k)
                    f[i][j][k] = (f[i][j][k] + g[j - 1][k][a[i] + tru[k]]) % mod;
                for (int k = 1; k <= idx; ++k)
                    g[j][k][a[i]] = (g[j][k][a[i]] + f[i][j][k]) % mod;
            }
            for (int j = 1; j < i; ++j)
                g[2][mp[a[j] - a[i]]][a[i]] = (g[2][mp[a[j] - a[i]]][a[i]] + 1) % mod;
        }
        // for (int i = 1; i <= n; ++i)
        //     for (int j = 1; j <= i; ++j)
        //         for (int k = 1; k <= idx; ++k)
        //             if (j <= 3)
        //                 printf("f[%lld][%lld][%lld] = %lld\n", i, j, tru[k], f[i][j][k]);
        printf("%lld %lld ", n, n * (n - 1) / 2);
        for (int i = 3; i <= n; ++i) {
            int s = 0;
            for (int j = i; j <= n; ++j)
                for (int k = 1; k <= idx; ++k)
                    s = (s + f[j][i][k]) % mod;
            printf("%lld ", s);
        }
        puts("");
    }
}

G

《模板:AC 自动机 III》

代码不贴了。

posted @   yhbqwq  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示