[ACM] CF水题记

Codeforces Round #736 (Div. 2)

A_Gregor and Cryptography

题意: 给你一个素数,让你找到 两个数 a,b 满足

[P mod a = P mod b ]

[2 le a <b le P ]

思路:随便找几个数,我们就可以构造出

  • 对于奇数,我们直接输出 (2)(n-1) 即可 ,mod 值为 (1)
  • 对于偶数,我们直接输出 (2)(n>>1) 即可,mod 值为 (0)
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 1e5 + 10;

void solve()
{
    int n;
    cin >> n;
    if( n&1 ){  /// odd
        cout << 2 << " " << n-1 <<endl;
    }else{ /// even
        cout << 2 << " " << (n>>1) << endl;
    }
}

int main()
{
    ios::sync_with_stdio(false);
    cout.tie(nullptr);
    cin.tie(nullptr);

    int t;
    cin>> t;
    while(t--){
        solve();
    }
}

B_Gregor and the Pawn Game

题意:在一个 (n*n) 的矩阵中,第一排为敌人的障碍,最后一排是自己的车车。问有多少个车能从最后一排开到第一排。开车的规则如下:

  • 直线向上,如果上方没有障碍
  • 如果左上方或右上方有障碍,也可以走,并且把哪一格的障碍消除

题解:就是一道贪心,因为障碍只在第一排且不能移动,我们就从左向右暴力,对于一个车

if(1,j-1) 有障碍那就ans++if else (1,j) 没有障碍那就ans++if else (1,j+1)有障碍那就ans++注意这里是if else

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 2e5 + 10;

void solve()
{
    int n,cnt = 0;
    cin >> n;
    string a,b;
    cin>> a >> b;
    a = "0" + a + "0";
    b = "0" + b;
    for(int i = 1 ; i <= n ; i ++){
        if( b[i] == '1' ){
            if( a[i - 1] == '1' ){
                cnt ++;
                a[i-1] = '0';
            }
            else if( a[i] == '0' ){
                cnt ++;
                a[i] = '0';
            }
            else if( a[i + 1] == '1'  ){
                cnt ++;
                a[i + 1] = '0';
            }
        }
    }

    cout << cnt <<endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cout.tie(nullptr);
    cin.tie(nullptr);

    int t;
    cin>> t;
    while(t--){
        solve();
    }
}

--

Codeforces Round #742 (Div. 2)

A. Domino Disaster

题意:

题解:

#include <bits/stdc++.h>
using namespace std;
 
void solve()
{
    int n;
    cin >> n;
    string s;
    cin >> s;
    for(int i = 0; i < s.length() ; i++){
        if( s[i] == 'L' || s[i] == 'R' ){
            cout << "LR";
            i++;
        }else{
            cout << (s[i]=='U'?'D':'U');
        }
    }
    cout <<endl;
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
 
    int t;
    cin >> t;
    while(t--){
        solve();
    }
 
    return 0;
}

B. MEXor Mixup

#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
const int N = 3e5 + 10;
ll xo[N];
 
void solve()
{
    ll a,b;
    cin >> a>> b;

    if( xo[a-1] == b ){
        cout << a << endl;
    }else if( (xo[a-1]^b) == a ){
        cout << a + 2 << endl;
    }else {
        cout << a + 1 <<endl;
    }
 
 
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    ll te = 0;
    for(int i = 1 ; i <= 300001;  i++){
        xo[i] = te = te^i;
        //cout << xo[i] << endl;
    }
 
 
    int t;
    cin >> t;
    while(t--){
        solve();
    }
 
 
 
    return 0;
}
/*
    125503 125003
 
*/

C. Carrying Conundrum

题意:Alice 在计算2数的加法的时候,要把进位向左多移动一位,现在给你最后算错的答案,问有多少个数对可以算出这个答案(包括进位的情况和不进位的情况)

题解: 分享后可以知道,第2个数(十位)会对第4个数(千位)有影响(十位进的位直接进到千位),第3个数会对第5个数影响,所以我们直接分奇偶来讨论就好了。

​ 每个数的组成方案的公式为

[a = a + 1 ]

​ 例如,4的组成为(1,3),(3,1),(2,2),(0,4),(4,0) 5种情况

​ 对于15005这个数,我们可以把他看成,奇数(105),偶数(50),通过上面的结论,我们可以知道有106个数对可组成 105,51个数对可组成50,但是(0,105)与(0,50)以及(105,0)与(50,0)这两个情况组成的答案我们应该排除,因为数为正整数

​ 所以我们直接把奇数,偶数分离用公式来计算就好了(a为奇数组成的数,b为偶数组成的数)

[(a+1)*(b+1)-2 ]

#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
const int N = 1e5 +10;
 
void solve()
{
    string n ;
    cin >> n ;
    int a=0,b=0;
    for(int i = 0 ; i < n.length() ; i++){
        if( (i+1)%2==0 ){
            a = a*10 + int(n[i] - '0');
        } else {
            b = b*10 + int(n[i] - '0');
        }
    }
 
    cout << (a+1)*(b+1) -2<< endl;
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
 
    int t;
    cin >>t;
    while(t--){
        solve();
    }
 
    return 0;
}

感悟: 规律题的话,首先需要确定,我们要找的规律是什么,这个题就是,一个数可以由多少个不同的数对组成(可以为2个相同的数,但是只视为一种方案,同时2数交换位置视为不同的方案数)。就是这个规律,我们从1开始算的话,最多算到15,20左右就把规律总结出来了。然后就是考虑到题目中的0的情况把这两种情况减掉就可以了

D. Expression Evaluation Error

题意: 给一个 (n , s)(n) 为一个数列的和,(s)为这个数列中数的个数,现在把 (n) 拆分成 (s) 个数,我们把这 s 个数视为 11 进制 求和,要使得这个11进制的数最大

题解: 对于10拆成9 + 1 ,会发现损失了1,所以我们要尽可能的保留最高位的数,并且要保证,之后可以拆成1 n-(s-i)就是在做这一步

#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
const int N = 1e5 +10;
 
int mypow(int x)
{
    int res = 1;
    for(int i = 0 ; i < x ; i++){
        res *= 10;
    }
    return res;
}

void solve()
{
    int n,s;
    cin >> n >> s;
    for(int i= 1; i < s ; i++){
        /// n-(s-i) 确保了最后可以补 1
        int x = mypow(int(log10(n - (s - i))) );
        cout << x << " ";
        n -= x;
    }
    cout << n <<endl;
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
 
    int t;
    cin >>t;
    while(t--){
        solve();
    }
 
    return 0;
}
原文地址:https://www.cnblogs.com/hoppz/p/15109223.html