Codeforces Round #742 (Div. 2) A-D

https://codeforces.com/contest/1567

A

  • 上面是左右排布的下面也一样,上面如果是上,下面就是下,反之上面是下,下面就是上
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
int main(){
    #ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t, n;
    string s;
    cin >> t;
    while(t--){
        cin >> n;
        cin >> s;
        for(int i=0;i<n;i++){
            if(s[i] == 'U') s[i] = 'D';
            else if(s[i] == 'D') s[i] = 'U';
        }
        cout << s << '\n';
    }
    return 0;
}

B

给你一组自然数里面的最小不存在和异或和,问这组数最少有多少个

  • 假设最小不存在是 a a a,异或是 b b b,那么至少应该有 [ 0 , a − 1 ] [0,a-1] [0,a1]个数在里面,设异或和为 x x x,那么应该加入 x ⊕ b x\oplus b xb,如果这个数是 a a a,那么需要调整,加入另外两个数让他们异或结果是 a a a,这可以做到;如果这个数不是 a a a,那么就加这个数即可
  • 需要预处理异或和
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
int a[MAXN];
int main(){
    #ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    a[1] = 1;
    for(int i=2;i<=300000;i++){
        a[i] = (a[i - 1] ^ i);
    }
    int t;
    cin >> t;
    int l, r;
    while(t--){
        cin >> l >> r;
        if(a[l - 1] == r){
            cout << l << '\n';
            continue;
        }
        else if((a[l - 1] ^ r) != l){
            l += 1;
        }else{
            l += 2;
        }
        cout << l << '\n';
    }
    return 0;
}

C

给出了一种特殊的加法方式,如果需要进位,那么往左边隔一位上面进,现在给出两个数经过这种加法得到的结果,问这两个数有多少种情况

  • 进位是在奇偶位置上分开进行的,故可以对奇偶位置分开来看,比如说如果和是 2021 2021 2021,那么分开看就是 1 1 1 22 22 22 1 1 1有几种组合情况呢?注意这里是正常的加法了,也就是 0 + 1 0+1 0+1 1 + 0 1+0 1+0这样两种, 22 22 22有多少种组合方式呢?, 0 + 22 , 1 + 21 , 2 + 20 , . . . , 22 + 0 0+22,1+21,2+20,...,22+0 0+22,1+21,2+20,...,22+0,这显然是 23 23 23种情况,但是题目要求只能是正数,所以应该把 0 0 0去掉,组合起来一共有多少个存在某个数为 0 0 0的呢?只有 1 + 0 , 22 + 0 1+0,22+0 1+0,22+0 0 + 1 , 0 + 22 0+1,0+22 0+1,0+22这样两种,所以答案应该是 ( a + 1 ) × ( b + 1 ) − 2 (a+1)\times(b+1)-2 (a+1)×(b+1)2
  • 上面所说的组合是这样进行的,比如说 0 + 1 0+1 0+1 1 + 21 1+21 1+21如何组合呢?就是下面这个意思
    在这里插入图片描述
  • 所以容易理解这不会出现重复
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
int main(){
    #ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    string s;
    cin >> t;
    while(t--){
        cin >> s;
        int a, b;
        a = b = 0;
        int len = s.length();
        for(int i=0;i<len;i++){
            if(i & 1){
                a *= 10;
                a += s[i] - '0';
            }else{
                b *= 10;
                b += s[i] - '0';
            }
        }
        cout << (a + 1) * (b + 1) - 2 << '\n';
    }
    return 0;
}

D

这题思路很简单,但是我愣是没写出来,感觉编码技术还是差得多…

  • 输入 a , b a,b a,b,他问的是把 a a a拆成 b b b个数,然后这 b b b个数如果按照 11 11 11进制算和,问什么时候这个和最大,打印这 b b b个数的方案
  • 这样考虑,就看 10 10 10这个数,如果让他变成 9 9 9,那么答案减少了 2 2 2,所以很明显分组的时候是高位剩下的越多越好,换句话说,能用 10 10 10绝不拆成 1 1 1,再换句话说,如果 10000 10000 10000要拆成若干个数,那肯定是先拆成 1000 , 1000... 1000,1000... 1000,1000...,然后再把 1000 1000 1000拆成 100 , 100... 100,100... 100,100...如果还不够,就把 100 100 100拆成 10 , 10... 10,10... 10,10...,再不够,就把 10 10 10拆成 1 , 1... 1,1... 1,1...
  • 同时,高位之间是不影响的,也就是说拆成 1000 + 1000 + 1000 1000+1000+1000 1000+1000+1000 2000 + 1000 2000+1000 2000+1000是一个效果
  • 那么这个过程怎么实现呢?因为这个 b b b很小,可以很暴力,我们先从 i = 1 e 9 i=1e9 i=1e9开始筛选,将 a a a一点点的拆,如果当前这个数 a a a不到 i i i,那么就 i = i 10 i=\frac{i}{10} i=10i;否则是不是应该分了呢?,那就是分出来一个 i i i,这时候 b − 1 b-1 b1,表示有一个数了,什么时候 b = 1 b=1 b=1,说明就剩下一个数,那这时候 a a a剩下多少就是多少;但这个时候需要考虑这个 i i i能不能分出来,比方说如果 100 100 100要分成 9 9 9个数,那不可能直接分出来个 100 100 100吧,这时候就要看分出来之后剩下的数还能不能分了,也就是比较一下 b − 1 b-1 b1 a − i a-i ai之间的大小关系,如果 a − i ≥ b − 1 a-i\geq b-1 aib1,说明还能分,哪怕是全分成 1 1 1,否则就不能分,这时候就往下走,也就是 i 10 \frac{i}{10} 10i
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
const int MAX = 1e9;
int main(){
    #ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t, s, n;
    cin >> t;
    while(t--){
        cin >> s >> n;
        vector<int> ans;
        for(int i=MAX;i>=1;i/=10){
            if(n == 1){
                ans.push_back(s);
                break;
            }
            if(s < i) continue;
            if(s - i < n - 1) continue;
            ans.push_back(i);
            s -= i;
            i *= 10;//这个位置技巧很好
            n -= 1;
        }
        for(auto i : ans) cout << i << ' ';
        cout << '\n';
    }
    return 0;
}
  • 这道题考验的是编码技巧,就是暴力会不会写的问题,事实证明我不会写暴力…
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值