Codeforces Round #619 (Div. 2)(A~C)

A. Three Strings

思路

  • 题意:给我们三个长度分别n的字符串a、b、c,现在我们对于位置 1<=i<=n,我们要进操作令a[i] = c[i]或者b[i]=c[i],我们必须在这两种操作选择之间选择一个,不能不选,当我们一次让i=1,2,3,,,n,依次执行上述操作,问通过我们合理操作能否是 字符串a == b??

  • 分析:分类讨论一下就好了,具体看代码吧

代码

#include<iostream>
#include<stdio.h> 
#include<stdlib.h>  
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<map>
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w", stdout); }
#define ios ios::sync_with_stdio(false) 
using namespace std;

#define ll long long 
#define db double
#define INF 0x3f3f3f3f
const int mod =998244353;
const int mxn = 50 + 10;


int main()
{
    /* fre(); */
    ios;
    int T;
    /* scanf("%d", &T); */
    cin >> T;
    while(T --)
    {
        string a, b, c;
        cin >> a >> b >> c;
        bool fg = 1;
        for(int i = 0; i < a.size(); i ++)
        {
            if(c[i] != a[i] && c[i] != b[i])
                fg = 0;
        }
        if(fg)
            cout << "YES\n";
        else
            cout << "NO\n";
    }

    return 0;
}

B. Motarack’s Birthday(贪心)

思路

  • 题意: 给我们n个数组成的序列,如果某个元素的值是-1,表示这个元素不存在,需要我们后面进行选择一个合适数字进行填写,到所有-1代表的空位中去,问我们我们应该填写那一个数字使在填写完我们选择的数字之后,是任意相邻的序列元素的差值的绝对值 的最大值 最小

  • 分析:一道贪心题,我们首先明白 相邻元素的差值是分两种情况的

  1. 在序列中两个元素都存在,且相邻的元素的差值–>这个种情况的差值已经是确定的值了,所以我们维护一下一个中情况的 最大差值a保留下 与第二种情况的产生的差值进行比较就行了
  2. 第二种情况产生在某个空为元素与两边真是存在的元素的差值,这个我们没法直接求出来,但是我们可以不断的维护位于所有位于空位旁边真实存在元素元素的最大值mx和最小值mn,,,最后为为了让我们选择的填空的元素设为k 与 mx、mn的差值的绝对值尽可能呢的小的话,就领 k = (mx + mn)/2,这样产生的最大差值设为 b = max(k - mn, mx - k)
  3. 最后最大差值就是 max(a,b),我们选择的最优填空数字为 k

代码

#include<iostream>
#include<stdio.h> 
#include<stdlib.h>  
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<map>
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w", stdout); }
#define ios ios::sync_with_stdio(false) 
using namespace std;

#define ll long long 
#define db double
#define INF 0x3f3f3f3f
const int mod =998244353;
const int mxn = 2e5 + 10;

ll ar[mxn];

int main()
{
    /* fre(); */
    /* ios; */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        int n;
        scanf("%d", &n);
        ll mx = -INF, mn = INF;
        for(int i = 1; i <= n; i ++)
            scanf("%lld", &ar[i]);
        ll mx_cha = 0;
        
        for(int i = 2; i <= n; i ++)
        {
            if(ar[i-1] == -1 && ar[i] != -1)
            {
                mx = max(mx, ar[i]);
                mn = min(mn, ar[i]);
            }
            if(ar[i-1] != -1 && ar[i] == -1)
            {
                mx = max(mx, ar[i-1]);
                mn = min(mn, ar[i-1]);
            }

            if(ar[i - 1] != -1 && ar[i] != -1)
                mx_cha = max(mx_cha, abs(ar[i] - ar[i - 1]));
        }

        ll val = (mx + mn) / 2;
        /* printf("mx = %d, mn = %d\n", mx, mn); */
        mx_cha = max(mx_cha, max(val - mn, mx - val)) ;
        printf("%lld %lld\n", mx_cha, val);
    }

    return 0;
}

C. Ayoub’s function(思维+组合数学+贪心)

思路

  • 题意
  1. 有一个有0、1组成的二进制个01字符串s
  2. 定义f(s) 为s中所有子串中 至少包含一个‘1’的子串的数量
  3. 现在有一个长度为为n的全由‘0’字符串组成的字符串a,让我们用‘1’替换掉其中m个字符(m<=n)得到字符串s,问经过合理的替换操作之后,可以得到的最大f(s)是多少??
  • 分析
  1. 这道题绝对考验我们的贪心能力以及思维,,,
  2. 既然a经过m次替换之后得到的s,那么在s中有m个1,n-m个0,我们要想让包含1点子串仅可能的多,那么 仅有全0组成的子串就要尽可能能的少(一个思维转变)
    3.我们现在将问题这样考虑,将 n-m个0,插入到m个1形成的空位中去,怎么插入才能的获得的 仅由0组成的子串尽可能的少??,,答案是将 n-m个零尽可能的均分插入到 m+1个空位中去(类似于“插板法”,这里用到了 贪心思想)
  3. 接下来有了上们的主要思路就是用,排列组合去求解方案数f(x) = 所有子串数量 - 全0子串的数量
    1. 考虑:n-m个0插入到m+1个空中,每个空位平均有 a = (n - m)/(m+1) 个0,但是这个时候我们如果不能整除话还会有剩余的0等待被插入,剩余的0的数量为:b = (n-m)%(m+1),我们先考将每个空位放a个0,产生的方案全0子串数为:a (1+a) / 2 * (m+1), 注意(a(1+b)/2表示 m+1个位置中每个位置产生的全0子串数量 ,而 “* (m+1)” 表示总共有 m+1个位置)
    2. 在这个的基础上我们在把剩下没有被插入的b个0插入到 前b个位置上,这个时候会产生的全0串为 (a+1) * b.注意(a+1表示 前b个位置中每个位置产生的新的全0子串 ,而 “* b” 表示有b个位置)
    3. 总的子串数量为:n*(n+1)/2
    4. 最后答案为:n*(n+1)/2 - a *(1+a) / 2 * (m+1)- (a+1) * b

代码

#include<iostream>
#include<stdio.h> 
#include<stdlib.h>  
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<string>
#include<queue>
#include<map>
void fre() { freopen("A.txt","r",stdin); freopen("Ans.txt","w", stdout); }
#define ios ios::sync_with_stdio(false) 
using namespace std;

#define ll long long 
#define db double
#define INF 0x3f3f3f3f
const int mod =998244353;
const int mxn = 2e5 + 10;

int main()
{
    /* fre(); */
    /* ios; */
    int T;
    scanf("%d", &T);
    while(T --)
    {
        ll n, m;
        scanf("%lld %lld", &n, &m);
        ll sum = n * (1 + n) / 2;       //长度为n的二进制串中的所有子串的数量
        ll a = n - m;                   //二进制字符串中 0 的数量
        ll b = m + 1;                   //二进制个字符串中m的个1形成b个可以插入0的位置数量
        ll c = a / b;                   //每个插入0的位置 平均要插入几个0,那么对于每一个插入位置,全步为0的子串的数量为c * ( 1 + c ) / 2, 因此b个插入位置总共有 b * c * (1 + c) / 2 个全部为0 的子串
        ll d = a % b;                   //平均每个位置插入c个0之后还剩下 d个零没有被插入,所以我们要将这个剩下的d个0平均放入到 前d个能插入0的位置,因此这个时候对于前d个插入位置中的每个位置又都增加了 c+1个 全部为0的子串,那么d个位置总共增加 d * (c + 1) 个全部为0 的子串
        ll e = b * c * (1 + c) / 2 + d * (c + 1);       //全为0子串的总数量
        printf("%lld\n", sum - e);
    }

    return 0;
}

D. Time to Run(模拟+构造欧拉路径)

思路

在这里插入图片描述

原创文章 220 获赞 292 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_34261446/article/details/106145447