牛客小白月赛79 (A~C)

125 阅读3分钟

AB简单直接上代码,C题有一些抽象

数位dp?

AC代码

直接从后往前找第一个偶数即可。

#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
#define endl '\n'
typedef long long ll;
const int N = 200010;
int n;
signed main()
{
    string s;
    cin >> s;
    int len = s.size();
    if ((s[len - 1] - '0') % 2 == 0) cout << 0 << endl;
    else
    {
        int cnt = 0;
        for (int i = len - 1; i >= 0; i--)
        {
            if ((s[i] - '0') % 2 != 0) cnt++;
            else
            {
                break;
            }
        }
        cout << cnt << endl;
    }
    return 0;
}

灵异背包?

AC代码

贪心,这里我写的有点复杂了,现将所有偶数求和,奇数放入另一个数组,并将奇数数组降序排序,如果奇数数组的长度为奇数,不加最后一个奇数,如果为偶数,则全加。
实际上,只需要全加起来sum,再判断sum的奇偶性即可,sum为奇数则减去最后一个最小的奇数。

#include<iostream>
#include<algorithm>
using namespace std;
#define int long long
#define endl '\n'
typedef long long ll;

const int N = 200010;
int a[N]; 
int n;

bool cmp(int a, int b)
{
    return a > b;
}
signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    int sum = 0;
    vector<int> v;
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        if (a[i] % 2 == 0) sum += a[i];
        else v.push_back(a[i]);
    }
    int len = v.size();
    sort(v.begin(), v.end(),cmp);
    if (len % 2 == 0)
    {
        for (int i = 0; i < v.size(); i++)
        {
            sum += v[i];
        }
    }
    else
    {
        for (int i = 0; i < v.size() -1; i++)
        {
            sum += v[i];
        }
    }
    cout << sum;
    return 0;

mex-gcd的乘积

题目详情

给你一个长度为n的数列。求这个数列中连续区间的mex 乘gcd⁡的最大值是多少?

形式化的: 定义f(l,r)=mex⁡(al,...,ar)×gcd⁡(al,...,ar) , l≤r求f(l,r)maxf(l,r)_{max}f(l,r)max​

关于mex:区间的mex被定义为区间中未出现的最小的非负整数,例如:

  • [2,2,1]的mex是0,因为0不在这个区间中
  • [3,1,0,1]的mex⁡是2,因为0,1在这个区间中,而2不在这个数组中
  • [0,3,1,2]的mex⁡是4,因为0,1,2,3在这个区间中,而4不在这个数组中

关于gcd⁡:连续区间的最大公约数是指一个数列中相邻的若干个数字的最大公约数,同时也是最大能被区间中所有数整除的数。特殊的,对于任意非负整数x,gcd⁡(0,x)=x,gcd⁡(x)=x,例如:

  • gcd⁡(6,4,3)=gcd⁡(gcd⁡(6,4),3)=gcd⁡(2,3)=1
  • gcd⁡(5,2,0)=gcd⁡(gcd⁡(5,2),0)=gcd⁡(1,0)=1
  • gcd⁡(5)=5gcd(5)=5

解题思路

这道题比较抽象,需要仔细读题,读懂题会发现其实并没有那么难。

  • 首先,当数组中全为0时,答案就是0,因为gcd(0)=0;
  • 其次,我们考虑让mex最大,这时取整个数组为区间,如果mex>1,则gcd=1。
  • 另外,我们让gcd最大,那么最好不要出现1,所以找有0的两位区间,这时mex就确定为1了,gcd就是0左右两边的数。
  • 最后,将几种情况都讨论一下取最大值即可。

AC代码

#include <iostream>
#include <vector>
#include <algorithm>
#define int long long
using namespace std;
signed main() {
    int n;
    cin >> n;
    int a[100010],b[100010];//b数组,判断该数是否存在

    for (int i = 1; i <= n; i++) 
    {
        cin >> a[i];
        b[a[i]] = 1;
    }
    
    if(*max_element(a+1,a+1+n)==0)//求数组最大值
        cout<<"0"<<endl;
    else
    {
        int res = 0;
        while(b[res]) res++;//找没出现的最小非负整数
        for(int i=1;i<=n;i++)
        {
            if(a[i]==0)
            {
                res = max(res,a[i-1]);
                res = max(res,a[i+1]);
            }
        }
       cout<<res<<endl;    
    }
    return 0;
}