新生赛002赛后补题

G - 0011  

NBUT - 1626 

这道题考察的是字符数组、字符串方面的知识。我在字符数组、字符串上的知识比较薄弱,一开始就卡在了要如何输入这串字符上,没想到直接开一个字符数组,用cin输入就可以了。 

在思维方面上,这题主要考验我们找特点、总结,找规律的能力。

根据题意所述,我们可以发现,一个合法的字符串要有相同数量的0和1,而且0在1前。可以概括为:

前面有几个连续的0,后面就有几个连续的1。
后面有几个连续的1,前面就有几个连续的0。

发现了这一点后就很简单了,下面上代码。

#include<iostream>
#include<cstring>
using namespace std;
char s[1006];//开比1000大一点的字符数组
int l;
int main()
{
  int n;
  cin>>n;
  while(n--)
  {
    l=0;
    int q=1;
    cin>>s;
    for(int i=0;i<=strlen(s)-1;i++)
    {
      if(s[i]=='1') l--;//字符型用得是''
      else if(s[i]=='0') l++;
      if(l<0) q=0;//在过程中后面连续的1多于前面连续的0 不合法
    }
    if(l>0) q=0;//前面连续的0多于后面连续的1 不合法
    if(q==0) printf("NO\n");
    else printf("YES\n");
  }
  return 0;
}

E - 由你来决定怎么颁奖

 CodeForces - 1264A 

这道题目的文字量也很大,而且题目还在最后还多加了一个条件,容易忽略:让奖牌的数量在满足其他条件的基础上最大。

i.e.是“换句话说、也就是说”的意思。补充:e.g.=for example。

题目大意是:在金牌数量小于银牌和铜牌的数量,并且获奖人数不能超过总人数的一半的基础上,让你去分配奖牌,使奖牌的数量最大。如果分配不了,则输出"0 0 0"。

这种题目就按题目的意思模拟一遍就ok了。

至于如何实现请见代码,不多bb了。

#include<iostream>
using namespace std;
int p[400010];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        int g=0,s=0,br=0;
        scanf("%d",&n);
        int mid=n/2;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&p[i]);
        }
        if(n<10) { printf("0 0 0\n"); continue; }
        while(p[mid]==p[mid+1]) mid--;   
        int a=1,b=1;
        for(int i=1;i<=mid-1;i++)
        {
            if(p[i]!=p[i+1]) 
            {
                if(a==1) a=0;
                else if(b==1) 
                {
                    if(s>g) b=0;
                    else s++;
                }
            }
            if(p[i]==p[i+1])
            {
                if(a==1) g++;
                else if(b==1) s++;
            }
        }
        g++;s++;br=mid-g-s;
        if(g<s&&g<br) printf("%d %d %d\n",g,s,br);
        else printf("0 0 0\n");
    }
}  

F - XorXor

 NBUT - 1615 

这道题只要你知识点都掌握了就不难。

知识点:异或运算——分别比较两个数的二进制的各个位数是否相同,若不同,则此位为1,若相同则此位为0。在C语言里," ^ "即异或运算符,可以直接使用。

容易发现:一个相同的数异或偶数次等于0,异或奇数次等于它本身。

Tip:一般先递增,达到一个最大值后,再递减的类似二项式展开式的数列各项都满足类似i*(n-i+1)的式子。

#include<iostream>
using namespace std;
int a[100010];
int b[100010];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=n;i++)
        {
            int f=i*(n-i+1);
            if(f%2==0) b[i]=0;
            else if(f%2==1) b[i]=a[i];
        }
        int ans=0;
        for(int i=1;i<=n;i++)
        {
            ans^=b[i];
        }
        printf("%d\n",ans);
    } 
}

 

D - Eat Candies

CodeForces - 1263A

这道题是道找数学本质题,也可以说是思维转换题。

题目的大意是给你三种不同的糖果,且三种不同的糖果的数量不确定。让你输入每种糖果的数量,问每天吃两种不同的糖果、每种一颗,最多可以吃几天。

那么,我们可以将这个问题转换成数学模型:给你三个数,使它们相互抵消,抵消至最小的绝对值要抵消几次(每次抵消1)。

于是,我们可以想到让最大值-第二大和最小值。但是又有一个问题,那就是这个值可能是负的,绝对值不小。这就说明,最小值中的部分数浪费了。

这三个数是可以拆开的。那么我们将浪费的数分成两份,一份用来帮助第二大值抵消最大值,一份可以抵消剩下的第二大的值。这样最后的值不是0就是1,即绝对值最小了。

注意这里的最大、第二大、最小都是不严格的。我们求的是这个过程中相互抵消的次数。

看清了问题的本质,代码实现就很容易了,下面上代码。

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
  int t;
  int s[4];
  scanf("%d",&t);
  while(t--)
   {
    for(int i=1;i<=3;i++)
    {       scanf(
"%d",&s[i]);     }
    sort(s
+1,s+4);     int sum=s[1]+s[2];     if(sum>s[3]) printf("%d\n",s[3]+(sum-s[3])/2);     else printf("%d\n",sum);   } return 0; }

 H - Perfect String

 CodeForces - 1265A 

这道题的文字量比较大,一开始看上去,会觉得好像很难的样子。但是,只要你读懂了题目的意思,其实并不难。考验的是你的读题、概括题意的能力。

题目的大意就是给你a、b、c三个元素,让你将任意一串含有‘?’的字符串改成任意相邻元素不相同的字符串,如果改不了,则输出"-1"。

那么只要从头开始判断当前元素是否和后一个元素是否相同,若相同,则输出"-1",结束判断。如果遇到"?",则将它换成一个与前后均不相同的元素。若在此过程中,没有中断判断,则输出改好的字符串。

#include<cstdio>
#include<cstring>
using namespace std;
char str[100005];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int q=1;
        scanf("%s",str);//这里不需要加&符号
        int len=strlen(str);//注意函数不能写在for循环的括号里,这样会导致超时的
        for(int i=0;i<=len-1;i++)
        {
            if(str[i]==str[i+1]&&str[i]!='?') {printf("-1\n");q=0;break;}
            else if(str[i]=='?') 
            {
                if(str[i-1]!='a'&&str[i+1]!='a') str[i]='a';
                else if(str[i-1]!='b'&&str[i+1]!='b') str[i]='b';
                else if(str[i-1]!='c'&&str[i+1]!='c') str[i]='c';
            }              
        }
        if(q==1) printf("%s\n",str);
    }
return 0; 
}
posted @ 2020-01-09 15:20  John-C  阅读(152)  评论(0编辑  收藏  举报