Codeforces Round 946 (Div.3)

C o d e f o r c e s   R o u n d   946   ( D i v . 3 ) \Huge{Codeforces~Round~946~(Div.3)} Codeforces Round 946 (Div.3)

题目链接:Codeforces Round 946 (Div. 3)

Problems A. Phone Desktop

题意

有无限个 3 × 5 3\times 5 3×5的二维方阵,然后给出x个 1 × 1 1 \times 1 1×1的方块和y个 2 × 2 2\times 2 2×2的方块,要求所有方块全部放在方阵里,求最少需要多少个方阵。

思路

每个方阵能放两个 2 × 2 2\times 2 2×2的方块,或者15个 1 × 1 1\times 1 1×1的方块,然后根据 2 × 2 2\times 2 2×2个数,求出至少需要多少个方阵,然后再根据 1 × 1 1\times 1 1×1方块个数判断需不需要加方阵。

标程

void Solved() {
    int x, y; cin >> x >> y;
    int sum1 = (y + 1) / 2;
    int sum2 = sum1 * 7;
    if(y & 1) sum2 += 4;

    sum2 -= x;
    if(sum2 < 0) {
        sum2 *= -1;
        sum1 += (sum2 + 14) / 15;
    }
    
    cout << sum1 << endl;
}

Problems B. Symmetric Encoding

题意

题目给出一个字符串 s s s,然后要求求解其加密前的字符串。

加密过程为:

  • 先将 s s s去重排序得到 s 2 s2 s2
  • 然后对 s 2 s2 s2进行首尾映射:
  • img
  • 最后根据映射改变 s s s

思路

根据加密过程进行模拟。

字符串是否加密,其去重排序的结果是不变的,然后用 m a p map map记录字母映射,然后对加密字符串解密即可。

标程

void Solved() {
    int n; cin >> n;
    string s; cin >> s;
    string ss = s, s1;

    sort(ss.begin(), ss.end());

    s1 = s1 + ss[0];
    for(int i = 1; i < n; i ++ ) {
        if(s1.back() != ss[i]) s1 = s1 + ss[i];
    }

    map<char, char> mp;
    int len = s1.size();
    for(int i = 0; i < len; i ++ ) {
        mp[s1[i]] = s1[len - i - 1];
        mp[s1[len - 1 - i]] = s1[i];
    }
    for(int i = 0; i < n; i ++ ) {
        cout << mp[s[i]];
    } cout << endl;
}

Problems C. Beautiful Triple Pairs

题意

题目给出一串长度为 n n n的数列 a a a,如果任意三元组 j ( 1 ≤ j ≤ n − 2 ) [ a j , a j + 1 , a j + 2 ] j (1 \le j \le n - 2) [a_j, a_{j + 1}, a_{j + 2}] j(1jn2)[aj,aj+1,aj+2]能够与其他三元组符合:任意一个位置不同其他两个位置相同,那么这个三元组就是美丽的,求其中美丽三元对的个数。

  • 3 ≤ n ≤ 2 ⋅ 1 0 5 3 \le n \le 2 \cdot 10^5 3n2105

思路

这道题的数据范围比较大,我们可以发现,对于任意三元组,如果我们需要找出所有三元组中有多少满足要求,其结果是:所有与它有至少两个相等的三元组个数,减去所有与它全部相等的三元组个数。

因此我们可以遍历一遍,然后用map存一下所有三元组中的两个,一共需要用三个map,然后再存一下每个三元组本身的个数,然后遍历一遍求解即可。

需要注意的是,我们求解过程中每个美丽三元组都加了两次,所以需要最后结果除以 2 2 2

标程

#define int long long 
#define PII pair<int, int>
#define fi first 
#define se second

void Solved() {
    int n; cin >> n;
    vector<int> a(n + 1);

    for(int i = 1; i <= n; i ++ ) {
        cin >> a[i];
    }
    map<PII, int> mp1, mp2, mp3;
    map<tuple<int, int, int>, int> mp;
    for(int i = 1; i <= n - 2; i ++ ) {
        mp[{a[i], a[i + 1], a[i + 2]}] ++;
        mp1[{a[i + 1], a[i + 2]}] ++;
        mp2[{a[i], a[i + 2]}] ++;
        mp3[{a[i], a[i + 1]}] ++;
    }
    int res = 0;
    for(int i = 1; i <= n - 2; i ++ ) {
        res += mp1[{a[i + 1], a[i + 2]}] - mp[{a[i], a[i + 1], a[i + 2]}];
        res += mp2[{a[i], a[i + 2]}] - mp[{a[i], a[i + 1], a[i + 2]}];
        res += mp3[{a[i], a[i + 1]}] - mp[{a[i], a[i + 1], a[i + 2]}];
    }
    
    cout << res / 2 << endl;
}

Problems D. Ingenuity-2

题意

题目给出上下左右四种操作,分别用“WESN"对应。现在有一个直升机H和漫游车 R R R,然后给出一串操作,要求每次选择直升机移动,或者漫游车移动,要求最后到达同意位置,题目要求输出一种具体解决方案,并且直升机或者漫游车都至少移动一次

思路

本题是一道模拟,我们考虑如下情况:一般地,如果讲所有操作全用一种机器移动,设最后坐标为 ( x , y ) (x,y) (x,y),若 x x x y y y为奇数,则题目无解,否则可以将两个机器都移动到 ( x 2 , y 2 ) (\frac{x}{2},\frac{y}{2}) (2x,2y)位置。

实现方法就是:每个机器都移动每种操作数的一半。

唯一需要注意的就是:

  • 不存在解决方案的情况:除了上述的横纵坐标出现奇数,还有就是当 n n n 2 2 2,且两个操作不一样的情况。
  • 当上下左右各出现一次的时候,需要特判,因为题目要求每个机器都至少移动一次。

标程

void Solved() {
    int n; cin >> n;
    string s; cin >> s;

    int x = 0, y = 0;
    map<char, int> mp;
    for(int i = 0; i < n; i ++ ) {
        if(s[i] == 'N') y ++, mp['N'] ++;
        if(s[i] == 'S') y --, mp['S'] ++;
        if(s[i] == 'W') x --, mp['W'] ++;
        if(s[i] == 'E') x ++, mp['E'] ++;
    }
    if((x & 1) || (y & 1) || (n == 2 && s[0] != s[1])) {
        cout << "NO\n"; return;
    }
    string ss = "WESN";
    int t = 0;
    for(auto i : ss) if(mp[i]) t ++;

    if(t == 4 && n == 4) {//判断EWSN的情况
        for(int i = 0; i < 4; i ++ ) {
            if(s[i] == 'W' || s[i] == 'E') cout << 'H';
            if(s[i] == 'S' || s[i] == 'N') cout << 'R';
        }
        cout << endl;
        return;
    }
    
    map<char, int> mp2;
    for(int i = 0; i < n; i ++ ) {
        if(mp2[s[i]] < mp[s[i]] / 2) cout << 'R', mp2[s[i]]++;
        else cout << 'H';
    }
    cout << endl;
}

Problems E. Money Buys Happiness

题意

作者每个月的工资为 k k k,每个月有购买幸福的机会,但是本月工资不能用来购买本月幸福,工资可以累计。每个月的幸福有价值和幸福度,作者希望 n n n个月过后自己的幸福度最多,求幸福度最多为多少?

数据范围:

  • 0 ≤ c i ≤ 1 0 8 , 1 ≤ h i ≤ 1 0 3 0 \le c_i \le 10^8,1 \le h_i \le 10^3 0ci108,1hi103 c i c_i ci表示幸福价值, h i h_i hi表示幸福度。
  • ∑ i h i ≤ 1 0 5 \sum_i h_i\le 10^5 ihi105
  • 1 ≤ n ≤ 50 , 1 ≤ k ≤ 1 0 8 1 \le n \le 50, 1 \le k \le 10^8 1n50,1k108

思路

跟据题目来看,这道题应该是一道 d p dp dp,但是状态转移方程不太好推。

容易注意到幸福度之和比较小,同时 n n n的数据范围也比较小,并且 O ( n × ∑ i h i ) O(n \times \sum_i h_i) O(n×ihi)的时间复杂度也不会超时。

通过观察发现,当幸福度最多时,满足幸福度最多,所用价值最少。因此我们考虑讲幸福度看作背包问题中的价值,幸福价值看作重量,然后把问题转化为求解幸福度最多,并且所用价值最少的情况。那么这道题就转化为了一道01背包问题。

标程

#define int long long 
const int INF = 0x7fffffff;

void Solved() { 
    int n, k; cin >> n >> k;
    vector<PII> a(n + 1);
    int sum = 0;

    for(int i = 1; i <= n; i ++ ) {
        int x, y; cin >> x >> y;
        a[i] = {x, y};
        sum += y;
    }
    int res = 0;
    vector<int> f(sum + 1, INF * 10000);//数据范围会爆int
    f[0] = 0;

    for(int i = 1; i <= n; i ++ ) {
        for(int j = sum - a[i].se; j >= 0; j -- ) {
            //当前工资需要满足能够买本月幸福和枚举的幸福,否则无法转移
            if((i - 1) * k >= a[i].fi + f[j]) {
                f[j + a[i].se] = min(f[j + a[i].se], f[j] + a[i].fi);
            }
        }
    }
    
    for(int i = sum; i; i -- ) {
        if(f[i] != INF * 10000) {
            res = i; break;
        }
    }
    cout << res << endl;
}
  • 14
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces Round 894 (Div. 3) 是一个Codeforces举办的比赛,是第894轮的Div. 3级别比赛。它包含了一系列题目,其中包括题目E. Kolya and Movie Theatre。 根据题目描述,E. Kolya and Movie Theatre问题要求我们给定两个字符串,通过三种操作来让字符串a等于字符串b。这三种操作分别为:交换a中相同位置的字符、交换a中对称位置的字符、交换b中对称位置的字符。我们需要先进行一次预处理,替换a中的字符,然后进行上述三种操作,最终得到a等于b的结果。我们需要计算预处理操作的次数。 根据引用的讨论,当且仅当b[i]==b[n-i-1]时,如果a[i]!=a[n-i-1],需要进行一次操作;否则不需要操作。所以我们可以遍历字符串b的前半部分,判断对应位置的字符是否与后半部分对称,并统计需要进行操作的次数。 以上就是Codeforces Round 894 (Div. 3)的简要说明和题目E. Kolya and Movie Theatre的要求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Codeforces Round #498 (Div. 3) (A+B+C+D+E+F)](https://blog.csdn.net/qq_46030630/article/details/108804114)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Codeforces Round 894 (Div. 3)A~E题解](https://blog.csdn.net/gyeolhada/article/details/132491891)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值