首页 > 其他分享 >AtCoder Beginner Contest 362 补题记录(A~E,G)

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

时间:2024-07-13 22:54:57浏览次数:14  
标签:AtCoder Beginner int yc yb ya read 补题 io

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]\) 中。然后考虑开两个前缀和分别记录左端点和右端点的和。

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

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

时间复杂度为 \(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

设 \(f_{i,j,k}\) 为当前选取的最后一个元素为 \(i\),选取了 \(j\) 个元素,等差数列的公差为 \(k\) 的方案数。

则可以枚举 \(i\),\(j\),\(k\) 和上一个选择的元素 \(p\),然后有转移方程 \(f_{i,j,k}\leftarrow f_{p,j-1,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(n^5)\),会超时。

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

设 \(g_{j,k,p}\) 表示选取 \(j\) 个元素,目前公差为 \(k\),且上一个元素值为 \(p\) 的方案数。

于是可以在枚举 \(f\) 的转移的时候一并转移上 \(g\)。此时 \(g\) 的转移为:\(g_{j,k,a_i}\leftarrow f_{i,j,k}\)。

因此 \(f\) 的转移也可以通过 \(g\) 来优化,即为:\(f_{i,j,k}\leftarrow g_{j-1,k,a_i+k}\)。

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

然后因为 \(a_i\le 10^9\) 所以你还需要对所有的元素离散化。但是因为目前时间复杂度为 \(O(n^4)\) 再多一只 \(\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》

代码不贴了。

标签:AtCoder,Beginner,int,yc,yb,ya,read,补题,io
From: https://www.cnblogs.com/yhbqwq/p/18300874

相关文章

  • Solution - Atcoder AGC021D Reversed LCS
    考虑到\(\operatorname{LCS}(T,T')\)这个形式实在是不太优美,考虑转化一下形式。感受一下,能够知道\(T\)的最长回文子序列\(|\operatorname{LPS}(T)|=|\operatorname{LCS}(T,T')|\)。具体证明可以见zhihu,本人暂时还没看懂。那么接下来对于单个串的\(\operatorname{LPS......
  • Solution - Atcoder ARC127E Priority Queue
    考虑转化一下,每个最后留下来的集合都相对的对应着一个被删除的集合。于是考虑去对被删除的数去计数。然后贪心的,去让每一次\(2\)操作删除的数都是前面加入中还剩下的最后加入的数(因为有的可能被前面的\(2\)操作删了)。对于证明,考虑到如果不是剩下的最后加入的,那么中间可能会......
  • 【atcoder】习题——位元枚举
    题意:求i&M的popcount的和,i属于0……N主要思路还是变加为乘。举个例子N=22,即10110假设M的第3位是1,分析N中:00110001110010000101发现其实等价于0010001100000001也就是左边第4位和第5位不变,右边第1位和第2位不变拼接起来,相当于0000~001101110011110110001101......
  • 个人赛补题
    round1范围很小用暴力+贪心,左右枚举,先拿再放。尽量放小的所以需要排下序includeinclude"map"include"algorithm"include"cmath"include"vector"include"set"include"queue"defineintlonglongusingnamespacestd;void......
  • Solution - Atcoder ABC177F I hate Shortest Path Problem
    考虑按题目所述的进行DP。设计状态\(f_{i,j}\)代表强制要求\((i,j)\)要走向\((i+1,j)\)最小的横坐标之差,这是因为对应的纵坐标之差是确定的。对于转移,考虑到对于\(j\not\in[a_i,b_i]\),直接从上面转移下来即可,即\(f_{i,j}\leftarrowf_{i-1,j}\)。对于\(j......
  • Solution - Atcoder ARC150D Removing Gacha
    考虑到每次操作都比定会选上一个点,于是答案可以表示为每个点被选中的次数之和。即令\(c_i\)为\(i\)点被选中的次数,答案即为\(E(\sum\limits_{i=1}^nc_i)\)。根据期望的线性性,考虑把答案的\(E\)拆到每个\(c_i\)上,即变为\(\sum\limits_{i=1}^nE(c_i)\)的形式。......
  • Denso Create Programming Contest 2024(AtCoder Beginner Contest 361)E-F
    E求一条树上的路径,使得走遍整棵树花费最小。我们容易发现树上的某条简单路径只需走一次,除此之外所有的路径都需要走两次,那么显而易见,我们需要求树的直径,之后将剩余的路径权值和乘二加上直径权值就可以。F数学题,对于数学题而言,个人感觉时间复杂度的计算对于题目的求解非常重......
  • AtCoder Beginner Contest 361
    AtCoderBeginnerContest361A-Insert给定一个长度为\(N\)的序列\(A\),现在希望将数字\(X\)插入到序列的第\(K\)个数字后面,变成一个新的序列\(B\)。输出序列\(B\)。\(K,N,A_i,X\le100\)模拟题。先读入\(N,K,X\)。接着在读入\(A\)的过程中一遍读入一遍输出,如果读到了第\(K......
  • AtCoder Beginner Contest 361)
    推荐个C++编程仓库模板https://github.com/yxc-s/programming-templateA-Insertvoidsolve(){ intn,k,x; cin>>n>>k>>x; vector<int>a(n); for(auto&x:a){ cin>>x; } a.insert(a.begin()+k,x); for(inti=0;......
  • Denso Create Programming Contest 2024(AtCoder Beginner Contest 361)
    DensoCreateProgrammingContest2024(AtCoderBeginnerContest361)\(A\)Insert\(AC\)循环结构。点击查看代码inta[200];intmain(){intn,k,x,i;cin>>n>>k>>x;for(i=1;i<=n;i++){cin>>a[i];cout......