Codeforces Round #742 (Div. 2) A~D题解

A. Domino Disaster

  • 题意
    给你一个 2 × n 2 \times n 2×n的网格,现在利用了 1 × 2 1\times 2 1×2的多米若骨牌填满了网格。给出了第一行的多米诺骨牌的状态。需要你构造出第二行的合法状态。

  • 解题思路
    如果是水平放置,那么第一行和第二行互补影响。如果是垂直放置,那么第二行的状态要和第一行的状态相反,即一个向上一个向下。所以如果是水平放置,我们就重复第一行的放置状态,否则就按相反状态放置即可。

  • AC代码

/**
  *@filename:A_Domino_Disaster
  *@author: pursuit
  *@created: 2021-09-05 22:36
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int t, n;
char s[N];
void solve(){
    char pre = ' ';
    for(int i = 1; i <= n; ++ i){
        if(s[i] == 'U'){
            printf("D");
        }
        else if(s[i] == 'D'){
            printf("U");
        }
        else{
            printf("%c", s[i]);
        }
    }
    puts("");
}
int main(){	
    scanf("%d", &t);
    while(t -- ){
        scanf("%d%s", &n, s + 1);
        solve();
    }
    return 0;
}

B. MEXor Mixup

  • 题意
    给你 a , b a,b a,b。需要你构造出最短的序列使得 M E X = a , X O R = b MEX=a,XOR=b MEX=a,XOR=b M E X MEX MEX表示序列中未出现的最小非负整数, X O R XOR XOR表示序列中的所有元素异或和。

  • 解题思路
    根据题目要求,我们要想让 M E X = a MEX=a MEX=a,那么 < a <a <a的所有元素都必须在序列中,那么序列长度至少为 l e n len len,同时,我们需要求异或和,如果直接异或求的话,那么难免会超时。所以这里需要通过异或前缀和预处理出 3 e 5 3e5 3e5的数据,当然,我们也可以通过性质,求 0 0 0~ n n n的异或和可以根据 n n n 4 4 4的余数确定:

    • 若余数为 0 0 0,则异或和为 n n n
    • 若余数为 1 1 1,则异或和为 1 1 1
    • 若余数为 2 2 2,则异或和为 n + 1 n +1 n+1
    • 若余数为 3 3 3,则异或和为 0 0 0

    这个性质不予证明,大家可以查阅相关资料手推或者记下来。
    处理完这个我们得到的异或和为 r e s res res,如果 r e s = b res = b res=b,那么我们没有必要添加元素了。如果不相等呢?我们至少还需要添加一个元素使得异或和为 b b b,假设添加的值为 x x x,那么 x = r e s x= res x=res^ b b b
    这个时候我们需要特判 x x x,因为如果 x = a x=a x=a我们是一定不能取的,这个时候我们就需要选取两个元素异或得到 a a a了,此时所需要添加的元素就是两个。
    至此题解。

  • AC代码

/**
  *@filename:B_MEXor_Mixup
  *@author: pursuit
  *@created: 2021-09-05 22:39
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int t, a, b;
void solve(){
    int res, len = a;
    int x = a - 1;
    if(x % 4 == 1)res = 1;
    else if(x % 4 == 2)res = a;
    else if(x % 4 == 3)res = 0;
    else res = x;
    if(res == b){
        cout << len << endl;
        return;
    }
    int temp = (res ^ b);
    if(temp == a){
        //说明不能选取。
        cout << len + 2 << endl;
    }
    else{
        cout << len + 1 << endl;
    }
}
int main(){	
    cin >> t;
    while(t -- ){
        cin >> a >> b;
        solve();
    }
    return 0;
}

C. Carrying Conundrum

  • 题意
    定义一种加法进位往前两位进,给定和 n n n,问有多少种正整数组合(a,b) ,使得和为 n n n

  • 解题思路
    此题有很多做法,例如dfs,dp,都是考虑是否进位。
    这里介绍最简单的方法,我们注意到,每次进位都是往前两位进位,那么换句话说,相邻的数是互不影响的,即奇偶位置不同的是互不影响的。所以我们可以按奇偶分开考虑:
    例如对于 12345 12345 12345,我们可以按奇偶性拆成 135 135 135 24 24 24,那么它们分开形成的数就是正常的加法了,往前一位进位,这样情况下的方案数为 n u m + 1 num +1 num+1,所以我们可以得到总方案数为 ( a n s 1 + 1 ) × ( a n s 2 + 1 ) (ans1+1)\times (ans2+1) (ans1+1)×(ans2+1),但还没有结束,注意到为正整数组合,该方案数为所有情况的方案数,那么还包括了 ( 0 , n ) , ( n , 0 ) (0,n),(n,0) (0,n),(n,0)这种,这两种方案是不符合的,所以最终答案为 ( a n s 1 + 1 ) × ( a n s 2 + 1 ) − 2 (ans1+ 1)\times(ans2+1)-2 (ans1+1)×(ans2+1)2

  • AC代码

/**
  *@filename:C_Carrying_Conundrum
  *@author: pursuit
  *@created: 2021-09-05 22:57
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

int t, n, a[12], len;
ll res;
void solve(){
    len = 0;
    int temp = n;
    while(temp){
        a[++ len] = temp % 10;
        temp /= 10;
    }
    ll ans1 = 0, ans2 = 0;
    for(int i = len; i >= 1; -- i){
        if(i & 1){
            ans2 = ans2 * 10 + a[i];
        }
        else{
            ans1 = ans1 * 10 + a[i];
        }
    }
    cout << (ans1 + 1) * (ans2 + 1) - 2 << endl;
}
int main(){	
    cin >> t;
    while(t -- ){
        cin >> n;
        solve();
    }
    return 0;
}

D. Expression Evaluation Error

  • 题意
    给定正整数的个数 n n n,同时给定在 10 10 10进制下的和 s s s,需要你构造出 n n n个数,使得它们用 11 11 11进制计算形成的和最大。

  • 解题思路
    由于我们是用 10 10 10进制表示但是是用 11 11 11进制计算,所以对于 19 19 19,我们转化成的值为 1 × 1 1 1 + 9 × 1 1 0 1\times 11^1+9\times 11^0 1×111+9×110。我们注意到,如果能构造出高位的的 10 10 10次幂,那么和就越高(因为基数为 11 11 11)。所以一开始我们可以将 s s s 10 10 10次幂分解出来。
    然后考虑能表达的个数 s u m sum sum,这里需要注意, s u m ≥ n sum\geq n sumn不影响,因为 10 + 10 = 20 10+10=20 10+10=20,只要没有进位,那么就是可行的。关键在于 s u m < n sum<n sum<n,我们需要凑数,那么破坏 10 10 10次幂我们肯定是从低位开始破坏,假设使第 i i i位的值减 1 1 1,那么第 i − 1 i-1 i1位的就可以多凑出 10 10 10个,这样我们就多出了 9 9 9个数。注意这里需要贪心的从低位开始凑,直到低位凑不了再转高位凑。
    处理完之后, s u m ≥ n sum\geq n sumn。这个时候我们需要考虑合并使其变成 n n n,合并需要从高位开始合并,注意细节处理即可。

  • AC代码

/**
  *@filename:D_Expression_Evaluation_Error
  *@author: pursuit
  *@created: 2021-09-06 00:09
**/
#include <bits/stdc++.h>
#define debug(a) cout << "debug : " << (#a)<< " = " << a << endl

using namespace std;

typedef pair<int,int> pii;
typedef long long ll;
const int N = 1e5 + 10;
const int P = 1e9 + 7;
const int INF = 0x3f3f3f3f;

//D直接无脑拆 拆出10^p p越大越好就行
int t, n, s;
int power[11];
void init(){
    power[0] = 1;
    for(int i = 1; i <= 9; ++ i){
        power[i] = power[i - 1] * 10;
    }
}
void solve(){
    vector<int> a;
    int sum = 0;
    while(s){
        a.push_back(s % 10);
        sum += s % 10;//sum表示为能凑成的最大10次幂的数。
        s /= 10;
    }
    while(sum < n){
        //这个时候我们需要凑。从低位到高位考虑。
        for(int i = 1; i < a.size(); ++ i){
            if(a[i] > 0){
                -- a[i], a[i - 1] += 10;
                sum += 9;
                break;//退出。即希望用低位凑。能不进到高位就不进到高位。
            }
        }
    }
    vector<int> res;
    for(int i = a.size() - 1; i >= 0; -- i){
        for(int j = 0; j < a[i]; ++ j){
            res.push_back(power[i]);
        }
    }
    while(res.size() > n){
        int x = res.back();
        res.pop_back();
        res.back() += x;
    }
    for(int i = 0; i < res.size(); ++ i){
        cout << res[i] << " ";
    }
    cout << endl;
}
int main(){	
    init();
    cin >> t;
    while(t -- ){
        cin >> s >> n;
        solve();
    }
    return 0;
}
posted @   unique_pursuit  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示