CodeForces Round #760 (Div. 3)

A. Polycarp and Sums of Subsequences

题目大意:

给七个不降序的数字,为三个数组合后得到的七种答案,求原来的三个数是哪些

思路:

由样例不难发现,第一个一定是三个数之一,因为没有数可以相加得到最小的第一个

然后发现,第二个也一定是三个数之一,因为不能两个第一个数相加,所以第二个也一定是数自身

最后一个数最大,一定是三个数之和,那么就遍历就可以了。

代码:

 

/*
************************************
***********emu^w^***********
 
*/
 
#include <bits/stdc++.h>
using namespace std;
 
const int N = 1510, M = 5e4 + 10;
 
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int q[8];
        for(int i = 1; i <= 7; i++) cin>>q[i];
        
        cout<<q[1]<<" "<<q[2]<<" ";
        for(int i = 3; i <= 6; i++) 
        {
            if(q[i] + q[1] + q[2] != q[7]) continue;
            
            cout<<q[i]<<endl;
            break;
        }
    }
}

 

B. Missing Bigram

题目大意:

把一个长度为n只有a和b组成的字符串转化为n-1个紧邻的二元字符串 例如

abbab -> ab bb ba ab 

然后抹掉其中一个 然后让你根据剩下几个二元字符串求原字符串

思路:

不难发现 每个字符串之间头尾相连,如果在中间就发现没有头尾相连的,那就可以直接发现抹除的是哪个了

情况1:

抹除的那个在中间部分,有二元串头尾不相连,直接在这个串之前输出每个的第一个,然后输出这个串,然后继续输出到最后一个;

情况2:

抹除的那个在两头,即每个都头尾相连,这时直接在最后加个a就行了,加a加b不影响

 

代码:

 

/*
************************************
***********emu^w^***********
 
*/

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

const int N = 110, M = 5e4 + 10;

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        cin>>n;
        string s[N];
        for(int i = 1; i <= n - 2; i++) cin>>s[i];
        
        if(n == 3)
        {
            cout<<s[1]<<"a"<<endl;
            continue;
        }
        else {
            bool flag = false;
            char a, b;
            int tes;
            for(int i = 2; i <= n - 2; i++)
            {
                if(s[i][0] == s[i - 1][1]) continue;
                else { //记录下来 在i的前边 缺一个 为s[i - 1][1] + s[i][0] 
                    flag = true;
                    tes = i; //在tes后输出  
                    a = s[i - 1][1], b = s[i][0];
                    break;
                }
            }
            
            if(!flag) {
                for(int i = 1; i <= n - 2; i ++)
                {
                    if(i == n - 2) cout<<s[i];
                    else cout<<s[i][0];
                }
                cout<<"a"<<endl;
                continue;
            }
            else {
                for(int i = 1; i <= n - 2; i++)
                {
                    if(i == tes) {
                        cout<<a<<b;
                        if(i == n - 2) cout<<s[i][1];
                        continue;
                    }
                    else {
                        if(i == n - 2) cout<<s[i];
                        else cout<<s[i][0]; 
                    }
                }
                cout<<endl;
                continue;
            }
        }
    }
}

 

C. Paint the Array

题目大意:找到一个数,能将给出的数组中被所有相隔的数整除,而不能被其他数整除

思路:自然而然的想到分类讨论求gcd然后遍历判断对错

代码:

 

/*
************************************
***********emu^w^***********
 
*/

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

const int N = 110, M = 5e4 + 10;

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        ll q[N];
        int n;
        cin>>n;
        for(int i = 1; i <= n; i++) 
            cin>>q[i];
            
        ll gcd1 = q[1], gcd2 = q[2]; // gcd1是奇数项的总gcd ..    
        for(int i = 3; i <= n; i++)
            if(i % 2 == 1) gcd1 = __gcd(gcd1, q[i]);
            else gcd2 = __gcd(gcd2, q[i]);
        
        bool flag = false;    
        for(int i = 1; i <= n; i++)
        if(i % 2 == 1) //用gcd2 去遍历奇数项 
        {
            if(q[i] % gcd2 == 0) {
                flag = true;
                break;
            }
        }
        
        if(!flag) {
            cout<<gcd2<<endl;
            continue;
        }
        else flag = false;
        
        for(int i = 1; i <= n; i++) 
            if(i % 2 == 0) 
                if(q[i] % gcd1 == 0) {
                    flag = true;
                    break;
                }
        if(!flag) {
            cout<<gcd1<<endl;
            continue;
        }
        else cout<<"0"<<endl;
            
        
        
        
    }
}

 

D. Array and Operations

题目大意:给一个数组,进行k次操作,每次操作可以选两个数踢出数组然后求两个数的商(向下整除),然后把剩余的数直接加入答案,求最小总和

思路:首先比较好想的是,尽量消除大的元素,那么就从小到大排序,然后对于从大到小的k * 2个元素进行操作就行(比较好想)

然后对于这个区间的贪心,首先想到的是朴素做法,就是尽量消除重复,等到没有重复元素的时候直接停止就OK,如果还有的话就加重复元素个数/2

但是这样写比较麻烦(写了一个小时而且还错了的屑)

所以应该想到朴素做法时直接找不用操作的条件

发现只要在区间里找到重复元素最多的元素个数,然后判断个数是否大于这个区间大小的一半就行了

对于每个元素,其他元素都能与之相消,唯独自己相消会多出个“1”,所以当最多的元素大于区间剩余元素个数的时候,相减,/2,然后加进答案就可以了

 

/*
************************************
***********emu^w^***********
 
*/

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

const int N = 110, M = 5e4 + 10;

int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        int n, k;
        cin>>n>>k;
        int q[N];
        for(int i = 1; i <= n; i++) cin>>q[i];
        sort(q + 1, q + n + 1);
        k *= 2;
        ll ans = 0;
        int nums = 0;
        for(int i = n; i >= n - k + 1; i--)
        {
            int j = i - 1;
            while(q[i] == q[j] && j >= n - k + 1) j--; // i - j是相同元素个数 j - n + k 是小的元素个数
            
            if(i - j >= j - n + k + nums) {
                ans += (i - j - j + n - k - nums) / 2;
                break;
            }
            else {
                nums += i - j;
                i = j + 1;
            }
             
        }
        
        for(int i = 1; i <= n - k; i++) ans += q[i];
        cout<<ans<<endl;
    }
}

 

其实这里还是写的有点麻烦了,直接找最多元素然后判断个数就行。。。。

 

 

posted @ 2021-12-15 09:45  lviy_ptilopsis^^  阅读(69)  评论(0)    收藏  举报