没怎么找工作,因为各种原因也没准备,偶然翻到了牛客网,发现以前还有个账号,又看了一下里面的题目,因为没怎么刷题,即兴练手。

里面一共有8题,做了一会没做完,之后补上,先写几题。

魔法币

时间限制:1秒

空间限制:32768K

小易准备去魔法王国采购魔法神器,购买魔法神器需要使用魔法币,但是小易现在一枚魔法币都没有,但是小易有两台魔法机器可以通过投入x(x可以为0)个魔法币产生更多的魔法币。 魔法机器1:如果投入x个魔法币,魔法机器会将其变为2x+1个魔法币 魔法机器2:如果投入x个魔法币,魔法机器会将其变为2x+2个魔法币 小易采购魔法神器总共需要n个魔法币,所以小易只能通过两台魔法机器产生恰好n个魔法币,小易需要你帮他设计一个投入方案使他最后恰好拥有n个魔法币。

输入描述:

输入包括一行,包括一个正整数n(1 ≤ n ≤ 10^9),表示小易需要的魔法币数量。

输出描述:

输出一个字符串,每个字符表示该次小易选取投入的魔法机器。其中只包含字符'1'和'2'。

输入例子1:

10

输出例子1:

122

大致思路

稍微计算一下,可以发现,只用魔法机器1生成的魔法币数量是: $$ 2^m-1$$ 只用魔法机器2生成的魔法币数量是: $$ 而这刚好可以写成一个完全的二叉树:

其中每一个父节点有两个子节点,左边的是采用机器1生成的,右边则是采用机器2生成的。可以看出每个数仅出现一次,说明机器1和机器2的组合唯一,因此可以采用倒推法计算出每一个机器。
首先通过计算出在哪一行,然后判断在该行是奇数还是偶数,奇数为1号,偶数为2号,计算完后再按公式返回上一行如此反复。
最后代码如下:

cpp
#include <stdio.h>
#include <string.h>
#include <math.h>
int main(void)
{
    int n;
    scanf("%d",&n);
    char a[30];
    int num = log(n+1)/log(2);
    int i,tmp=num;
    while (tmp>1)
    {
        int stmp =n+2-pow(2,tmp);
        if(stmp%2 == 0)
           {
               a[tmp-1]='2';
               n =(n-2)/2;
           }
           else
           {
               a[tmp-1]='1';
               n = (n-1)/2;
           }
           tmp--;
    }
    a[0]= n%2?'1':'2';
           for (i=0;i<num;i++)
           printf("%c",a[i]);
           }

相反数

时间限制:1秒

空间限制:32768K

为了得到一个数的"相反数",我们将这个数的数字顺序颠倒,然后再加上原先的数得到"相反数"。例如,为了得到1325的"相反数",首先我们将该数的数字顺序颠倒,我们得到5231,之后再加上原先的数,我们得到5231+1325=6556.如果颠倒之后的数字有前缀零,前缀零将会被忽略。例如n = 100, 颠倒之后是1.

输入描述:

输入包括一个整数n,(1 ≤ n ≤ 10^5)

输出描述:

输出一个整数,表示n的相反数

输入例子1:

1325

输出例子1:

6556

思路

直接求出每一位逆序相加即可,比较简单,直接贴代码:

cpp
#include <stdio.h>
 
int main(void)
{
    int i=0,k=1,n,tmp,rev[5];
    scanf("%d",&n);
    tmp=n;
    while(tmp>9)
    {
        rev[i]=tmp%10;
        tmp =(tmp-rev[i])/10;
        i++;
        k *=10;
    }
    rev[i]=tmp;
    int result=n;
    i=0;
    while(k>0)
    {
        //printf("%d",rev[i]);
        result += rev[i]*k;
        i++;
        k /=10;
         
         
    }
    printf("%d",result);
}

字符串碎片

时间限制:1秒

空间限制:32768K

一个由小写字母组成的字符串可以看成一些同一字母的最大碎片组成的。例如,"aaabbaaac"是由下面碎片组成的:'aaa','bb','c'。牛牛现在给定一个字符串,请你帮助计算这个字符串的所有碎片的平均长度是多少。

输入描述:

输入包括一个字符串s,字符串s的长度length(1 ≤ length ≤ 50),s只含小写字母('a'-'z')

输出描述:

输出一个整数,表示所有碎片的平均长度,四舍五入保留两位小数。

如样例所示: s = "aaabbaaac" 所有碎片的平均长度 = (3 + 2 + 3 + 1) / 4 = 2.25

输入例子1:

aaabbaaac

输出例子1:

2.25

思路

用一个计数器,遍历一遍,碰到不相同的就加1。代码如下:

cpp
#include <stdio.h>
#include <string.h>
 
int main(void)
{
    char s[50];
    scanf("%s",s);
    char *p=s;
    int len=1,frac=1;
    while(*(p+1) != '\0')
    {
        len++;
        if(*p != *(p+1))
            frac++;
        p++;
    }
    printf("%.2f",(len+0.0)/frac);
}

游历魔法王国

时间限制:1秒

空间限制:32768K

魔法王国一共有n个城市,编号为0~n-1号,n个城市之间的道路连接起来恰好构成一棵树。 小易现在在0号城市,每次行动小易会从当前所在的城市走到与其相邻的一个城市,小易最多能行动L次。 如果小易到达过某个城市就视为小易游历过这个城市了,小易现在要制定好的旅游计划使他能游历最多的城市,请你帮他计算一下他最多能游历过多少个城市(注意0号城市已经游历了,游历过的城市不重复计算)。

输入描述:

输入包括两行,第一行包括两个正整数n(2 ≤ n ≤ 50)和L(1 ≤ L ≤ 100),表示城市个数和小易能行动的次数。 第二行包括n-1个整数parent[i](0 ≤ parent[i] ≤ i), 对于每个合法的i(0 ≤ i ≤ n - 2),在(i+1)号城市和parent[i]间有一条道路连接。

输出描述:

输出一个整数,表示小易最多能游历的城市数量。

输入例子1:

5 2 0 1 2 3

输出例子1:

3

思路

找出树的最大长度和L比较,如果大于L,那就直接是L+1,如果小于L,剩下的必须走别的路,且必须走两次,所以最后结果是maxlen+(L-maxlen)/2。代码如下:

cpp
#include <stdio.h>
 int getlen(int n,int p[50])
 {
     int mlen=0,tmp,i,k;
     for (i=n-2;i>=0;i--)
     {
         k=i;
         tmp=0;
         while(p[k]!=0)
         {
             tmp++;
             k=p[k]-1;
         }
         tmp++;
         mlen=(mlen>tmp)?mlen:tmp;
     }
     return mlen;
 }
int main(void)
{
    int i,n,L;
    int p[50];
    scanf("%d%d",&n,&L);
    for(i=0;i<n-1;i++)
        scanf("%d",&p[i]);
     int maxlen;
     maxlen =getlen(n,p);
    maxlen = (maxlen>L)?L:(maxlen+int((L-maxlen)/2));
    maxlen++;
    printf("%d",maxlen);
     
}

重排数列

时间限制:1秒

空间限制:100768K

小易有一个长度为N的正整数数列A = {A[1], A[2], A[3]..., A[N]}。 牛博士给小易出了一个难题: 对数列A进行重新排列,使数列A满足所有的A[i] * A[i + 1](1 ≤ i ≤ N - 1)都是4的倍数。 小易现在需要判断一个数列是否可以重排之后满足牛博士的要求。

输入描述:

输入的第一行为数列的个数t(1 ≤ t ≤ 10), 接下来每两行描述一个数列A,第一行为数列长度n(1 ≤ n ≤ 10^5) 第二行为n个正整数A[i](1 ≤ A[i] ≤ 10^9)

输出描述:

对于每个数列输出一行表示是否可以满足牛博士要求,如果可以输出Yes,否则输出No。

输入例子

2 3 1 10 100 4 1 2 3 4

输出例子

Yes No

大致思路

比较是否是4的倍数和奇数的数目,如果前者大于等于后者,必然是满足的。还有一种情况是前者等于后者减一,此时不存在非4倍数的偶数。 最后代码如下:

cpp
#include <stdio.h>
int Isarray(int n, int a[100000])
{
    int n1=0,n2=0,n4=0,i=0;
    for(;i<n;i++)
    {
        if(a[i]%4==0)
            ++n4;
        else if(a[i]%2==0)
             ++n2;
        else
             ++n1;
    }
    //printf("%d,%d,%d,%d\t",n1,n2,n4,n);
    if (n==1 && n4 )
        return 1;
    if(n4 > (n1-1))
        return 1;
    else if((n4 == n1-1) && (n2 == 0) )
        return 1;
    else
        return 0;
    }
int main(void)
{
    int i,j,t,n,a[100000],b[10];
    scanf("%d",&t);
      
    for(j=0;j<t;j++)
    {
        scanf("%d",&n);
    for(i=0;i<n;i++)
        scanf("%d",&a[i]);
    b[j]=Isarray(n,a);
    }
    for(j=0;j<t;j++)
    if(b[j])
        printf("Yes\n");
    else
        printf("No\n");
    return 0;
}