我是靠谱客的博主 伶俐向日葵,最近开发中收集的这篇文章主要介绍Codeforces Round #847 (Div. 3) A-ECodeforces Round #847 (Div. 3),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Codeforces Round #847 (Div. 3)

文章目录

  • Codeforces Round #847 (Div. 3)
    • A. Polycarp and the Day of Pi
    • B. Taisia and Dice
    • C. Premutation
    • D. Matryoshkas
    • E. Vlad and a Pair of Numbers

比赛网址

A. Polycarp and the Day of Pi

题目大意

给你一个字符串,让你判断字符串中的数字于 π pi π 有多少位相同的(同第一个开始算) 输入字符串不大于30

思路/证明

水题不解释

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
string Check = "3141592653589793238462643383279";
lli total_ask;
signed main()
{
    ios::sync_with_stdio(0); cin.tie(0), cout.tie(0);
    cin >> total_ask;
    while(total_ask--){
        string put; lli Count = 0;
        cin >> put;
        for(int temp = 0 ; temp < put.size() ; temp++){
            if(put[temp] == Check[temp]) Count++;
            else break;
        }
        cout << Count << "n";
    }
    return 0;
}

B. Taisia and Dice

题目大意

n n n 个骰子,每个骰子从 1 1 1 6 6 6 ,现在有 n n n 个骰子,他们的和是 s s s ,现在
拿走其中最大的一个,其余的骰子之和为 r r r, 问可能的骰子结果是啥

思路/证明

水题,最喜欢这种输入任意一个的题了,不是贪心就是找规律,本题可以用贪心来做

我们可以求出最大值,然后贪心的选取之前的骰子即可

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
lli total_ask, have, origin, final;
void solution(lli give, lli target, lli Max){
    if(give == 0) return;
    lli Limit = target - (give - 1);
    if(Limit > Max){
        cout << Max << " ";
        solution(give - 1, target - Max, Max);
    }else{
        cout << Limit << " ";
        solution(give - 1, target - Limit, Max);
    }
}
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> total_ask;
    while(total_ask--){
        cin >> have >> origin >> final;
        solution(have - 1, final, origin - final);
        cout << origin - final << "n";
    }
    return 0;
}

C. Premutation

题目大意

给你一个长度为 n n n 的排列 即 p = a 1 , a 2 , … , a i , … , a n p = a_1, a_2, dots, a_i, dots ,a_n p=a1,a2,,ai,,an

现在输出给出 n n n 次输出,第 i i i输出都会将第 i i i 个数字去除

问:原本排列是什么

思路/证明

yysy, 还是很水,给的所有数据中只有一个第一个数字于其他不一样,那它就是排列的
开头数字,后面的就是准确的了,直接拼在一起即可

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
lli total_ask, have;
signed main()
{
    ios::sync_with_stdio(false); cin.tie(0), cout.tie(0);
    cin >> total_ask;
    while(total_ask --){
        cin >> have;
        vector<vector<lli>> info(have + 5, vector<lli>(have + 5));
        for(int temp = 1 ; temp <= have ; temp++){
            for(int temp2 = 1 ; temp2 <= have - 1 ; temp2++)
                cin >> info[temp][temp2];
        }
        lli first = info[1][1], index = 1;
        for(int temp = 2 ; temp <= have ; temp++){
            if(info[temp][1] != first){
                if(info[temp + 1][1] == info[temp][1]) {first = info[temp][1]; break;}
                else {index = temp ; break;}
            }
        }
        cout << first << " ";
        for(int temp = 1 ; temp <= have - 1 ; temp++)
            cout << info[index][temp] << " ";
        cout << "n";
    }
    return 0;
}

D. Matryoshkas

题目大意

给你一串数列,问其中的连续序列有多少个

思路/证明

一开始尝试模拟,原本以为是 O ( n ) O(n) O(n),结果好像会大得多,超时,发现可以用堆积木的想法来实现

我们可以通过计算不同积木之间的落差来确定到底有多少个连续对

如果当前这个数字于下一个数字不连续,那么就直接加上它的数量即可

注意:我们统计的是下降过程,最后一步可以通过添加一个空项实现,具体的
计数可以用map实现

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
lli total_ask, have;
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> total_ask;
    while(total_ask--){
        cin >> have;
        map<lli,lli> info;
        for(lli temp = 0 , num; temp < have ; temp++){
            cin >> num;
            info[num]++;
        }
        lli Count = 0;
        vector<pair<lli,lli>> num;
        for(auto pr : info) num.push_back(pr);
        num.push_back(make_pair(num[num.size() - 1].first + 1, 0));
        for(int temp = 0 ; temp < num.size() - 1 ; temp++){
            if(num[temp].first == num[temp + 1].first - 1){
                if(num[temp].second > num[temp + 1].second)
                    Count += num[temp].second - num[temp + 1].second;
            }
            else
                Count += num[temp].second;
        }
        cout << Count << "n";
    }
    return 0;
}

E. Vlad and a Pair of Numbers

题目大意

给你一个数字 x x x, 问是否存在两个数 a a a, b b b 可以使得 x = a ⊕ b = a + b 2 x = aoplus b = frac{a + b}{2} x=ab=2a+b , ⊕ oplus X O R XOR XOR

存在输出任意 a a a, b b b ,不存在输出 − 1 -1 1

思路/证明

不会真的有人像我一样吧 ⊕ oplus 看成 O R OR OR了吧,甚至还把方法想出来了,甚至代码都敲好了…

没关系,下次拿出来考别人…

这道题最优的算法是 O ( 1 ) O(1) O(1)的,但很可惜,我不会粗略的解释如下:

试一下a=n+n/2,b=2n-a和2n+1-a,然后试一下a=n+n/2+1,b=2n-a和2n+1-a。如果这四种组合都不是可行解就是无解

但我没想到,当我想到了一个奇技淫巧:

首先我们将给的数和它的二倍转化为二进制

之后我们从低位向高位逐个判断:

假设num1 为 原数的二进制表示, num2 为原数乘于2的二进制表示

如果 num1的第 i i i 位是1 , 那么两个答案的第 i i i位一定是一个1,一个0

如果这个时候num2的第 i i i位是1, 1 和 0 相加肯定也是1,所以我们可以让一个答案的第 i i i位为1,另一个为0

但如果num2此时是0, 那么就需要两个答案的 i − 1 i-1 i1位是1,然如果此时num1 的 i − 1 i-1 i1位是1,则无解,但我们不管它,最后再判断

同理,num1的第 i i i 位是0时,我们在更具num2来判断

注意最后要验证一下a,b是否满足条件即可

代码(我的奇技淫巧)

#include<bits/stdc++.h>
using namespace std;
typedef long long int lli;
lli total_ask, give;
lli List[35];
signed main()
{
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> total_ask;
    for(lli temp = 0, num = 1 ; temp < 35 ; temp++, num *= 2)
        List[temp] = num;
    while(total_ask --){
        cin >> give;
        if(give & 1) {cout << "-1n"; continue;}
        vector<int> num1, num2;
        lli one = give, two = give << 1;
        for(int temp = 0 ; temp < 30 ; temp++){
            num1.push_back((one >> temp) & 1);
            num2.push_back((two >> temp) & 1);
        }
        vector<int> ans1(30,0), ans2(30,0);
        for(int temp = 1 ; temp < 30 ; temp ++){
            if(num2[temp] == 0){
                if(num1[temp] == 1){
                    ans1[temp] = 1;
                    ans1[temp - 1] = 1; ans2[temp - 1] = 1;
                }else{
                    ans1[temp] = 0; ans2[temp] = 0;
                }
            }else{
                if(num1[temp] == 1) ans1[temp] = 1;
            }
        }
        lli first = 0, second = 0;
        for(int temp = 0 ; temp < 30 ; temp++){
            if(ans1[temp]) first += List[temp];
            if(ans2[temp]) second += List[temp];
        }
        if(!(first ^ second == one && first + second == two)) {cout << "-1n"; continue;}
        cout << first << " " << second << "n";
    }
}

F,G就不补了,图论表示还不是咋会

最后

以上就是伶俐向日葵为你收集整理的Codeforces Round #847 (Div. 3) A-ECodeforces Round #847 (Div. 3)的全部内容,希望文章能够帮你解决Codeforces Round #847 (Div. 3) A-ECodeforces Round #847 (Div. 3)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(35)

评论列表共有 0 条评论

立即
投稿
返回
顶部