现在的位置: 首页 > 综合 > 正文

2011百校联动“菜鸟杯”程序设计公开赛(现更新5道)

2013年05月04日 ⁄ 综合 ⁄ 共 3769字 ⁄ 字号 评论关闭

作为一个真正意义上的菜鸟,A掉了4题。。。。。

比赛暴漏了很多问题,最大的就是代码控制能力不强,很多简单的题不能在很短的时间内敲出来,说明还是打的少。以后尽量少看别人代码,争取通过自己的思考做题,这样碰到同类的题才能迅速A掉。

下面是我做出来的5道题的简单分析:

其中的1002、1005、1008都是真正意义上的水题。

1002:

每5个字符转换一次,遇到字母就是0,遇到数字就是1,然后得出这5个数字对应的10进制数字,对应到26个英文字母就是答案。

代码如下:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;

#define max(a, b) a > b ? a : b
#define min (a, b) a < b ? a : b
#pragma comment(linker, "/STACK:102400000,102400000")
char ans[26] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};

int main()
{
    int len;
    char str[10010];
    int sum;
    while(scanf("%d", &len) != EOF)
    {
        scanf("%s", str);
        for(int i = 0; i < len; i += 5)
        {
            sum = 0;
            for(int j = i; j < i + 5; ++j)
            {
                if(str[j] >= '0' && str[j] <= '9')
                    sum += pow(2.0, 4 - j % 5);
            }
            printf("%c", ans[sum]);
        }
        printf("\n");
    }
    return 0;
}

1005:

KFC排队问题,简单的数学问题。读清楚题就可以迅速A掉。

代码如下:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
int b, d, f, p;
char que[10010];

int sum(char a)
{
    if(a == 'A')
        return (b + d + f);
    else if(a == 'B')
        return (2 * b + 2 * d + p);
    else
        return (3 * b + 3 * d + 2 * p);
}

int main()
{
    int n;
    int ans, len, mincost;
    while(scanf("%d%d%d%d%d", &n, &b, &d, &f, &p) != EOF)
    {
        mincost = 9999999;
        for(int k = 0; k < n; ++k)
        {
            scanf("%s", que);
            len = strlen(que);
            ans = 0;
            for(int i = 0; i < len; ++i)
                ans += sum(que[i]);
            if(mincost > ans)
            mincost = ans;
        }
        printf("%d\n", mincost);
    }
    return 0;
}

1008:

比较2个字符串,看看主串中含有多少个不重叠的子串,开始以为是KMP,发现很多人迅速水过,想着应该是纯暴力啊。。。KMP可不是一时半会就可以理解的。于是果断暴力,果断A掉了。。。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
char s[1000050], p[10];

int main()
{
    int ncase;
    int lens, lenp;
    int i, j, k, sign;
    int sum;
    scanf("%d", &ncase);
    while(ncase--)
    {
        scanf("%s%s", s, p);
        lens = strlen(s);
        lenp = strlen(p);
        sum = 0;
        for(i = 0; i < lens; ++i)
        {
            int k = i;
            for(j = 0; j < lenp; ++j)
            {
                if(s[k] == p[j])
                    k++;
                else
                    break;
            }
            if(j == lenp)
            {
                sum++;
                i += lenp - 1;
            }
        }
        printf("%d\n", sum);
    }
    return 0;
}

1001和1006是比较难的。其中1006是比赛后A的。。。

1001:

可以把式子分解为:(y-x)(y+x)=n,设y-x=a,y+x=b.然后通过枚举得出结果。但是TLE了。后来听数学系的同学给了一点思路,发现通过均值不等式可以大大减少枚举的个数,通过对num开平方,从中间开始向下找因子,找到的第一个肯定就是x的最小值(x=(a-b)/2),a-b的值越小,说明ab越接近,这点均值不等式可以说明。所以做法就是先对num开平方,得到temp,然后从temp向下枚举,找到的第一个a,b就是答案。但是需要注意的是x是正整数,所以a和b不能相等。相等x=0,这点注意一下就可以了。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

int main()
{
    int ncase;
    int num, temp;
    bool flag;
    scanf("%d", &ncase);
    while(ncase--)
    {
        scanf("%d", &num);
        flag = false;
        temp = (int)sqrt(num * 1.0);
        for(int i = temp; i >= 1; --i)
        {
            if(num % i != 0)
                continue;
            else
            {
                if((i + num / i) % 2 == 0 && i != num / i)
                {
                    printf("%d\n", (num / i - i) / 2);
                    flag = true;
                    break;
                }
            }
        }
        if(!flag)
            printf("-1\n");
    }
    return 0;
}

1006:

这道题确实是一个难度很大的找规律题,后来发现matrix67大神博客上有这个数列的介绍,只要看下这篇博客就应该能搞定了。其实就是一个简单的模拟而已。

就是判断上一个数列的1,2,3的个数,比如1221,则从左向右遍历,发现有1个1,所以是“11”,然后有2个2,所以加上“22”,变成“1122”,然后是1个1,加上“11”,成为“112211”。其实就是判断数列从左到右重复数字出现的个数。

文章链接:http://www.matrix67.com/blog/archives/3870/comment-page-1

代码如下:

#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
int p[32] = {0, 1, 2, 2, 4};
string s[32] = {"", "1", "11", "21", "1211"};

void fast(int n)
{
    int len = s[n - 1].length();
    int sum = 1;
    for(int i = 0; i < len - 1; ++i)
    {
        if(s[n - 1][i] != s[n - 1][i + 1])
        {
            if(i == len - 2)
            {
                s[n] += (sum + '0');
                s[n] += s[n - 1][i];
                s[n] += '1';
                s[n] += s[n - 1][i + 1];
            }
            else
            {
                s[n] += (sum + '0');
                s[n] += s[n - 1][i];
                sum = 1;
            }
        }
        else
        {
            sum++;
            if(i == len - 2)
            {
                s[n] += (sum + '0');
                s[n] += s[n - 1][i];
                break;
            }
        }
    }
    p[n] = s[n].length();
}

int main()
{
    int n;
    for(int i = 5; i <= 30; ++i)
        fast(i);
    while(scanf("%d", &n) && n)
    {
        printf("%d\n", p[n]);
    }
    return 0;
}


//打表~
#include<cstdio>

int main()
{
	int n;
	int p[30] = {1, 2, 2, 4, 6, 6, 8, 10, 14, 20, 26, 34, 46, 62, 78, 102, 134, 176, 226, 302, 408, 528, 678, 904, 1182, 1540, 2012, 2606, 3410, 4462};
	while(scanf("%d", &n), n)
		printf("%d\n", p[n - 1]);
	return 0;
}

抱歉!评论已关闭.