首页 > 其他分享 >Educational Codeforces Round 137 (Rated for Div. 2) A-F

Educational Codeforces Round 137 (Rated for Div. 2) A-F

时间:2022-10-23 23:46:34浏览次数:83  
标签:Educational Rated cout int 复杂度 t2 Codeforces cin dp

比赛链接

A

题解

知识点:数学。

\(4\) 位密码,由两个不同的数码组成,一共有 \(C_4^2\) 种方案。从 \(10-n\) 个数字选两个,有 \(C_{10-n}^2\) 种方案。结果为 \(3(10-n)(9-n)\)。

时间复杂度 \(O(n)\)

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

bool solve() {
    int n;
    cin >> n;
    for (int i = 1;i <= n;i++) {
        int x;
        cin >> x;
    }
    cout << 3 * (10 - n) * (9 - n) << '\n';
    return true;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) {
        if (!solve()) cout << -1 << '\n';
    }
    return 0;
}

B

题解

知识点:构造。

显然最小价值是 \(2\) 。把 \(1\) 和 \(2\) 分两端放即可。

时间复杂度 \(O(n)\)

空间复杂度 \(O(1)\)

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

bool solve() {
    int n;
    cin >> n;
    for (int i = 2;i <= n;i++) cout << i << ' ';
    cout << 1 << '\n';
    return true;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) {
        if (!solve()) cout << -1 << '\n';
    }
    return 0;
}

C

题解

知识点:贪心。

发现,可以将一段连续的盖子向左移,等效于把最后一个盖子移到第一个左边。因此,找到一个无盖且右边连续有盖的位置,从连续有盖的一段选一个最小的和无盖的位置交换,如果最小的比无盖的大那就不交换。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

int a[200007];
bool solve() {
    int n;
    cin >> n;
    string s;
    cin >> s;
    s = "?" + s;
    for (int i = 1;i <= n;i++) cin >> a[i];

    for (int i = 1;i <= n - 1;i++) {
        if (s[i] == '0' && s[i + 1] == '1') {
            int mi = i;
            for (int j = i + 1;j <= n && s[j] == '1';j++) {
                if (a[j] < a[mi]) mi = j;
            }
            swap(s[i], s[mi]);
        }
    }
    int sum = 0;
    for (int i = 1;i <= n;i++) {
        if (s[i] == '1') sum += a[i];
    }
    cout << sum << '\n';
    return true;
}

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int t = 1;
    cin >> t;
    while (t--) {
        if (!solve()) cout << -1 << '\n';
    }
    return 0;
}

D

题解

知识点:枚举。

第一个串显然是从第一个 \(1\) 开始截取到最后,现在考虑从第一个串截取出第二个串填补第一个串的 \(0\) 。

显然要从第一个 \(0\) 开始填。注意到,只有 \(0\) 前面的 \(1\) 可以通过截取向右移动与 \(0\) 重合。枚举前面每个 \(1\) 通过截取与第一个 \(0\) 重合即可,截取方法有很多,第一种,以各个 \(1\) 为起点,截取固定长度,保持 \(1\) 与 \(0\) 重合;第二种,从第一个 \(1\) 开始截取,截取不同长度,使各个 \(1\) 和 \(0\) 重合。

发现复杂度是和从第一个 \(1\) 开始连续 \(1\) 的长度有关,但因为是随机数据,因此不可能太长,可以看作常数。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>

using namespace std;

int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    string s;
    cin >> s;
    int pos = s.find('1');
    if (!~pos) {
        cout << 0 << '\n';
        return 0;
    }
    string s1 = s.substr(pos);
    pos = s1.find('0');
    string ans = s1;
    for (int i = 0;i < pos;i++) {
        string s2 = s1;
        for (int j = pos;j < s1.size();j++) {
            if (s1[j - pos + i] == '1') s2[j] = '1';
        }
        ans = max(ans, s2);
    }
    cout << ans << '\n';
    return 0;
}
/* #include <bits/stdc++.h>

using namespace std;

string elz(string s) {
    for (int i = 0;i < s.size() - 1;i++)
        if (s[i] == '1') return s.substr(i);
    return s.substr(s.size() - 1);
}
int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n;
    string s;
    cin >> n >> s;
    bitset<1000005> a(s), b(s);
    string ans = a.to_string();
    for (int i = 1;i <= 10;i++)
        ans = max(ans, (a | (b >> i)).to_string());
    cout << elz(ans) << '\n';

    return 0;
} */

E

题解

知识点:线性dp。

考虑设 \(dp[i]\) 为造成不少于 \(i\) 点伤害的最小时间。

先考虑 \(p_1,p_2\) 单独射击的转移:

dp[i] = min(dp[max(0LL, i - (p1 - s))] + t1, dp[max(0LL, i - (p2 - s))] + t2);

再考虑,\(p_2\) 在 \(p_1\) 的 \(j\) 轮时间中调整,配合 \(p_1\) 在第 \(j\) 轮同时射击。此时 \(p_1\) 伤害是 \((j-1)(p_1 - s)\) ,\(p_2\) 伤害是 \(\lfloor\frac{(j\cdot t_1 - t_2)}{t_2}\rfloor(p_2-s)\) ,同时射击伤害 \(p_1+p_2-s\) ,共计 \((j-1)(p_1 - s) + \lfloor\frac{(j\cdot t_1 - t_2)}{t_2}\rfloor(p_2-s) + (p_1+p_2-s)\) 。(同理 \(p_1\) 配合 \(p_2\) 同时射击)。

ll dmg = (j - 1) * (p1 - s) + (t1 * j - t2) / t2 * (p2 - s) + (p1 + p2 - s);
dp[i] = min(dp[i], dp[max(0LL, i - dmg)] + t1 * j);

时间复杂度 \(O(h^2)\)

空间复杂度 \(O(h)\)

代码

#include <bits/stdc++.h>
#define ll long long

using namespace std;

ll dp[5007];
int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int p1, p2;
    ll t1, t2;
    cin >> p1 >> t1;
    cin >> p2 >> t2;
    int h;
    ll s;
    cin >> h >> s;
    dp[0] = 0;
    for (int i = 1;i <= h;i++) {
        dp[i] = min(dp[max(0LL, i - (p1 - s))] + t1, dp[max(0LL, i - (p2 - s))] + t2);
        for (int j = 1;j <= i;j++) {
            if (t1 * j >= t2) {
                ll dmg = (j - 1) * (p1 - s) + (t1 * j - t2) / t2 * (p2 - s) + (p1 + p2 - s);
                dp[i] = min(dp[i], dp[max(0LL, i - dmg)] + t1 * j);
            }
            if (t2 * j >= t1) {
                ll dmg = (j - 1) * (p2 - s) + (t2 * j - t1) / t1 * (p1 - s) + (p1 + p2 - s);
                dp[i] = min(dp[i], dp[max(0LL, i - dmg)] + t2 * j);
            }
        }
    }
    cout << dp[h] << '\n';
    return 0;
}

F

题解

知识点:排列组合,枚举。

我们考虑每个点对答案的贡献,显然是从他第一次出现开始计算。

比如某点在第 \(i\) 组区间出现,那么已经进行了 \(i-2\) 次操作了,产生 \(3^{i-2}\) 个集合。在这之后还有 \(n-i+1\) 次操作,如果操作时另一个区间有这个点,那么或和且能继承这个点继续;如果没有这个点,那么或和异或能继承这个点继续,注意无论以后有没有这个点都只有两个分支能使这个点有贡献,所以共 \(2^{n-i+1}\) 个集合是有这个点的,最后总贡献是 \(3^{i-2}2^{n-i+1}\) 。

要特别注意,第一个区间出现的点,之前的操作也是 \(0\) 次 ,并且之后的操作也只有 \(n-1\) 次,最终通式是 \(3^{\max(i-2,0)}2^{\min(n-i+1,n-1)}\) 。

接下来考虑如何记录某个点第一次出现的位置 \(lst[i]\) 。朴素枚举是 \(n^2\) 的,我们需要优化。显然出现过的点之后跳过就行了,我们记录每个点能跳跃到的位置 \(nxt[i]\) 即可,对于区间 \([l,r]\) ,如果某个点 \(i\) 没出现过,那么 \(nxt[i]\) 可以更新为 \(r[i]\) ;否则出现过,我们需要跳跃,同时更新这个点以后能跳跃到的位置,\(nxt'[i] = \max(nxt[i],r),i = nxt[i]\) ,注意需要保存一下旧位置,再更新完 \(nxt[i]\) 再更新 \(i\) 。

时间复杂度 \(O(n)\)

空间复杂度 \(O(n)\)

代码

#include <bits/stdc++.h>

using namespace std;

const int mod = 998244353;

int l[300007], r[300007], lst[300007], nxt[300007];
int pow2[300007], pow3[300007];
int main() {
    std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n;
    cin >> n;
    memset(lst, -1, sizeof(lst));
    pow2[0] = 1;
    pow3[0] = 1;
    for (int i = 1;i <= n;i++) {
        pow2[i] = 1LL * pow2[i - 1] * 2 % mod;
        pow3[i] = 1LL * pow3[i - 1] * 3 % mod;
    }
    for (int i = 1;i <= n;i++) cin >> l[i] >> r[i];
    for (int i = n;i >= 1;i--) {
        for (int j = l[i];j <= r[i];j++) {
            if (lst[j] == -1)lst[j] = i, nxt[j] = r[i];
            else {
                int tmp = nxt[j];
                nxt[j] = max(nxt[j], r[i]);
                j = tmp;
            }
        }
    }
    int ans = 0;
    for (int i = 0;i <= 300000;i++) {
        if (lst[i] == -1) continue;
        ans = (ans + 1LL * pow3[max(lst[i] - 2, 0)] * pow2[min(n - lst[i] + 1, n - 1)]) % mod;
    }
    cout << ans << '\n';
    return 0;
}

标签:Educational,Rated,cout,int,复杂度,t2,Codeforces,cin,dp
From: https://www.cnblogs.com/BlankYang/p/16820064.html

相关文章

  • Codeforces Round #829 (Div. 2) D. Factorial Divisibility(数学)
    题目链接题目大意:\(~~\)给定n个正整数和一个数k,问这n个数的阶乘之和能不能被k的阶乘整除既:(a\(_{1}\)!+a\(_{2}\)!+a\(_{3}\)!+....+a\(_{n}\)!)\(~\)%\(~\)k!\(~\)==......
  • Codeforces 1682 D Circular Spanning Tree
    题意1-n排列,构成一个圆;1-n每个点有个值0或者1,0代表点的度为偶数,1代表点的度为计数;询问能否构成一棵树,树的连边在圆内不会相交,在圆边上可以相交,可以则输出方案。提示1.......
  • Codeforces Round #758 (Div.1 + Div. 2) C
    C.GameMaster//不明白为什么tag上没有二分我二分一下就过了我们显然知道判断是否能打赢全部直接通过连边来判断是否能遍历全部点如何连边:我们同组一定相连对于排......
  • CodeForces-1143#C 题解
    正文♦时间复杂度:\(\mathcal{O}(n)\)思维题,不需要建树。设数组\(a\)记录每一个节点是否尊重它的父节点,数组\(b\)记录是否有节点尊重它,特别的,叶子节点必然不被尊重。......
  • Educational Codeforces Round 138
    EducationalCodeforcesRound138这把是真的丢了大脸。Dashboard$\color{Green}{★}\\$表示赛时做出。$\color{Yellow}{★}\\$表示赛后已补。$\color{Red}{★}......
  • Codeforces 823B
    题意:对若干正整数二元组\((x_i,t_i)\),求一个实数\(x_0\),使得\(max\{t_i+|x_i-x_0|\}\)最小。n<=1e5。思考:​ 虽然问的是\(x_0\),但不妨对这个最小的最大值进行二分,也......
  • Educational Codeforces Round 138 (Rated for Div. 2) A-E
    比赛链接A题解知识点:贪心。注意到\(m\geqn\)时,不存在某一行或列空着,于是不能移动。而\(m<n\)时,一定存在,可以移动。时间复杂度\(O(1)\)空间复杂度\(O(1)\)代......
  • Dashboard - Educational Codeforces Round 138 (Rated for Div. 2) - Codeforces
    Dashboard-EducationalCodeforcesRound138(RatedforDiv.2)-Codeforces这场比赛写的就很菜了。D题有点思路但是没想到是求是去求不满足条件的序列。1.Problem......
  • Codeforces Round #828 (Div. 3)
    CodeforcesRound#828(Div.3)1.Problem-D-Codeforces只要找有因子2的个数即可。只要因子个数是大于等于n的即可。voidslove(){cin>>n;fel(i,1,n)cin......
  • Codeforces Round #756 (Div. 3) E1
    E1.EscapeTheMaze(easyversion)我们显然遍历根节点到叶结点的同时维护最短距离然后在return的时候看该点距离是否大于最近的朋友的距离要是大于的话我们显然可以......