首页 > 其他 > 详细

新生赛002赛后补题

时间:2020-01-09 16:40:05      阅读:82      评论:0      收藏:0      [点我收藏+]

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; 
}

我们要注意,这三个数是可以拆开的。

新生赛002赛后补题

原文:https://www.cnblogs.com/Cnxz/p/12146622.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!