关闭

UESTC 第五届ACM趣味程序设计竞赛第一场(热身赛,非原创题) 解题报告

标签: ACM题解
1268人阅读 评论(0) 收藏 举报
分类:

第一次写解题报告,水平有限,欢迎补充!


这次的题目稍微排个难度顺序吧(仅个人观点)

Problem D    The Heros          字符串查找

Problem F     三国杀  模拟题

Problem G    懒惰的妹纸  简单的数学题

Problem E     Ants Run!          数学题

Problem H    Fruit Ninja          数学题

Problem C    UESTC冠军杯   模拟题


Problem DThe Heros

简单的字符串查找问题,由于数据范围很小,可以写一个裸的查找,也可以敲KMP,或者什么都不想写的话可以直接用strstr()乱搞过去了

至于strstr()函数的具体实现,不知道是否为KMP算法


Problem F三国杀

乍一看有人以为是线段树,其实就是很简单的模拟题

对于"N1 S Num"操作,用一个equip[i]的数组来维护,每次更新equip[i].dmg(攻击)和euip[i].def(防守)

对于"K A B"操作,先计算dis(A , B) = min(B - A , B + N - A) (当A < B时)

Dis(A,B) = dis(A , B) - equip[A].dmg + equip[B].def ,检查其是否小于等于1即可。

有一点字符串处理,小心一点就是。


Problem G懒惰的妹纸

很基础的数学题,讨论几种情况就行了

<1>t1 < a

<2>a <= t1 <= b , t1 - t < a

t1 - t >= a

<3>t1-t > b

<4>t1 - t <= b


ProblemEAnts Run!

需要动一下脑子的数学题

题目的要求是任何一只蚂蚁追赶到他前一只蚂蚁就会终止(第一只蚂蚁则追到最后一只)

首先,当所有蚂蚁速度都相同的时候,他们会永远地转圈圈。

否则,我们考虑这样一队蚂蚁,他们的速度为4 3 2 1

我们做出他们和前一只蚂蚁的速度差,得到3 -1 -1 -1

如果这样一队蚂蚁在圆上,只有可能第一只蚂蚁能追到最后一只蚂蚁

也就是说,我们可以将这一队蚂蚁一开始放在圆上的一个点(两两之间距离无穷小),那么这队蚂蚁走完这个圆就是第一只蚂蚁和最后一只蚂蚁的速度差的这个值(我们称之为“相对速度”)跑完全程

再考虑这样的蚂蚁队列,速度为3 2 1 4 3 2 1

我们实际上可以看作是两队蚂蚁3 2 1 | 4 3 2 1

同样可以照上述方式处理得到和前一只蚂蚁的相对速度:2 -1 -1 3 -1 -1 -1

这样两队蚂蚁,我们当然可以将每一队放在圆的一个点上,这个时候,队1的蚂蚁头要追队2的尾,队2的头要追队1的尾,由于我们得到的是相对速度,可以将每一队的蚂蚁尾看作在圆上不动。

为了使游戏时间尽可能长,我们当然希望的是两队蚂蚁头同时到达另一队的尾,所以即两个头的相对速度跑完全程

同理,我们可以推广到N队蚂蚁的情况。


ProblemHFruit Ninja

这个题很蛋疼,一开始看到数据在long long的范围内,觉得很难搞。

但是读题发现,(1 <= M , N <= 50) ,感觉貌似很水的一道题,是不是那个long long的范围在吓我们,于是乱搞一通,一交,WA了。。。

之后很久都不知道很大的答案是如何得到的。

想多了就知道55……5这样坑爹的情况貌似是可以构造出很大的答案的。

现在讨论如下的情况:

当m % 10 == 0 时,一定可以得到INF(只用选择一个10的倍数往上加就行了)

否则,当m%5 == 0时,

<1>若n % 5 == 0,则一定可以得到INF

<2>若n % 5 != 0,则可能出现55……5的情况。

这个时候,我们需要计算一下,由于1<=M<=50,则这是可取的M的值为5,15,25,35,45.

55……5 = 5 * a + k * M (5 * a为初始分数,k为正整数)

等式两边同时除以 5,即

11……1 = a + k * (M / 5)


当M = 5时,11……1 = a + k,则55555LL这个数为最大的一次各位数相等

当M = 15时,11……1 = a + k * 3,11……1 mod 3(“1”的个数从5个开始)得到的值为2,0,1,2,0,1……

故此时取“1”,得到的值尽可能大,即M=5时,5555555LL(7个“5”)会出现最大的一次各位数相等

当M = 25时,11……1 = a + k * 5,11……1 mod 5 得到的值是1,1,……故此时取“非1的值”,就不会得到各位数相等的数,故答案是INF

当M = 35时,11……1 = a + k * 7,11……1 mod 7 得到的值是2 ,0,1,4,6,5,2,0,1,4,……故此时取“3”,就不会得到各位数相等的数,故答案是INF

当M = 45时,11……1 = a + k * 9,11……1 mod 9 得到的值是5,6,7,8,0,1,2,3,4,5,……故此时去“4”,得到的值尽可能大,即M=45时,5555555555555LL(13个“5”)会出现最大的一次各位数相等

否则,最大情况就是max(9999 + n + ((9999 + n) % 5 : n : 0), 10000 + m)


Problem C    UESTC冠军杯

我只想说,这个是一个很恶心的模拟题,没有任何思考难度,仅仅是恶心,看到比赛时仅一人通过就知道了。。。

这道题周日晚上我上晚自习开始敲,敲得比较慢,由于之前做恶心模拟题留下阴影了,所以很谨慎,每敲一部分就开始测试一下数据,敲了整整2个小时码完了这道题。

总之,没做过同一类题目的同学还是要做一下这道题来练练手。


之后附上自己的代码吧:

Problem D

/*
 *  ID:     Allen_3
 *  Prob:   The Heros
 *  LANG:   C++
*/
#include<cstdio>
#include<cstring>
using namespace std;

struct node
{
    char str[52];
};  //node

node temp[12];

int main()
{
    int n , m;
    scanf("%d" , &n);
    for (int i = 0;i < n;i ++)
        scanf("%s" , temp[i].str);
    scanf("%d" , &m);
    for (int i = 0;i < m;i ++)
    {
        bool flag = false;
        char str[52];
        scanf("%s" , str);
        for (int i = 0;i < n;i ++)
            if (strstr(str , temp[i].str) != NULL)
            {
                printf("A new hero discovered\n");
                flag = true;
                break;
            }
        if (!flag)
            printf("Just an ordinary person\n");
    }   //

    return 0;
}   //main

Problem F

/*
 *  ID:     Allen_3
 *  Prob:   Three Kingdoms
 *  LANG:   C++
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;

#define     output      "test.txt"

struct node
{
    int dmg , def;
};  //node

int T , n , m;
node equip[1002];

inline int min(int a , int b)
{
    if (a < b)
        return a;
    return b;
}   //min

int main()
{
    //freopen(output , "w" , stdout);
    scanf("%d" , &T);
    for (int i = 0;i < T;i ++)
    {
        printf("Case #%d:\n" , i + 1);
        memset(equip , 0 , sizeof(equip));
        char ch;
        scanf("%d%d" , &n , &m);
        scanf("%c" , &ch);      //\n
        for (int i = 0;i < m;i ++)
        {
            scanf("%c" , &ch);
            if (ch == 'K')
            {
                int u , v , dis;
                scanf("%d%d" , &u , &v);
                if (u < v)
                    dis = min(v - u , u + n - v);
                else
                    dis = min(u - v , v + n - u);
                if (dis - equip[u].dmg + equip[v].def <= 1)
                    printf("Yes!\n");
                else
                    printf("I'm sorry.\n");
            }
            else
            {
                int u = 0 , num;
                while (ch != ' ')
                {
                    u = u * 10 + (ch - '0');
                    scanf("%c" , &ch);
                }   //
                scanf("%c" , &ch);          // + or -
                scanf("%d" , &num);
                if (ch == '+')
                {
                    equip[u].def = num;
                }
                else
                {
                    equip[u].dmg = num;
                }
            }
            scanf("%c" , &ch);  //\n
        }   //
        printf("\n");
    }   //  for T

    return 0;
}   //main

Problem G

/*
 *  ID:     Allen_3
 *  Prob:   Lazy Girl
 *  LANG:   C++
*/
#include<cstdio>
using namespace std;

int main()
{
    int T;
    scanf("%d" , &T);
    for (int i = 0;i < T;i ++)
    {
        int a , b , t , t1;
        scanf("%d%d%d%d" , &a , &b , &t , &t1);
        if (t1 <= a)
            printf("0.0000\n");
        else if (t1 - t >= a)
        {
            if (t1 <= b)
                printf("%.4f\n" , (double)t / (double)(b - a));
            else
            {
                if (t1 - t >= b)
                    printf("0.0000\n");
                else
                    printf("%.4f\n" , (double)(b + t - t1) / (double)(b - a));
            }
        }
        else
        {
            if (t1 <= b)
                printf("%.4f\n" , (double)(t1 - a) / (double)(b - a));
            else
                printf("1.0000\n");
        }
    }   //for i

    return 0;
}   //main

Problem E

/*
 *  ID:     Allen_3
 *  Prob:   Ants Run!
 *  LANG:   C++
*/
#include<cstdio>
using namespace std;

#define     pi      3.1415926
#define     INF     3f3f3f3f

int T , n , r;
int a[10002];

int main()
{
    scanf("%d" , &T);
    for (int i = 0;i < T;i ++)
    {
        bool flag = false;
        scanf("%d%d" , &n , &r);
        for (int i = 0;i < n;i ++)
        {
            scanf("%d" , &a[i]);
            if (i && a[i] != a[i - 1])
                flag = true;
        }
        if (!flag)
        {
            printf("Inf\n"); continue;
        }
        a[n] = a[0];
        int sum = 0;
        for (int i = 0;i < n;i ++)
        {
            a[i] = a[i + 1] - a[i];
            if (a[i] > 0)
                sum += a[i];
        }
        printf("%.3f\n" , 2 * pi * (double)r / (double)sum);
    }   //for i _ T

    return 0;
}   //main

Problem H

代码和题解有一定出入,题解是之后想出来的数学办法,对于M=5,M=15,M=45的情况是枚举出来的答案

/*
 *  ID:     Allen_3
 *  Prob:   Fruit Ninja
 *  LANG:   C++
*/
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

#define     input       "test.txt"
#define     output      "result.txt"

#ifdef unix
#define     LL_FMT      "%lld"
#else
#define     LL_FMT      "%I64d"
#endif

int a[2002];
int T , cnt = 0;
long long ans , n , m;

inline long long max(long long x , long long y)
{
    if (x > y)
        return x;
    return y;
}   //max

long long solve(int x)
{
    long long num = 5555LL;
    for (int i = 1;i <= 100;i ++)
    {
        num = num * 10LL + 5LL;
        if (!((num - x) % m))
            return (num + m + n);
    }   //for i
}   //solve

int main()
{
    //freopen(input  , "r" , stdin);
    //freopen(output , "w" , stdout);

    for (int i = 1;i <= 10000;i ++)
        if (!(i % 5))
            a[cnt ++] = i;

    scanf("%d" , &T);
    for (int i = 0;i < T;i ++)
    {
        printf("Case #%d: " , i + 1);
        scanf(LL_FMT LL_FMT , &m , &n);
        //printf(LL_FMT" "LL_FMT" ", m , n);
        if (!(m % 10LL))
        {
            printf("INF\n");
        }
        else if (!(m % 5LL) && (m % 10LL))
        {
            if (!(n % 5LL))
            {
                printf("INF\n");
            }
            else
            {
                if (m == 35 || m == 25)
                {
                    printf("INF\n"); continue;
                }
                ans = 0;
                for (int i = 0;i < cnt;i ++)
                    ans = max(ans , solve(a[i]));
                printf(LL_FMT"\n" , ans);
            }
        }
        else
        {
            ans = 9999LL + n;
            if (!(ans % 5LL))
                ans += m;
            if (10000LL + m > ans)
                ans = 10000LL + m;
            printf(LL_FMT"\n" , ans);
        }

    }   //for i _ T

    return 0;
}   //main

Problem C

代码略丑,请见谅。。。

/*
 *  ID:     Allen_3
 *  Prob:   UESTC Champion Cup
 *  LANG:   C++
*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define    output       "result.txt"

struct _info
{
    char name[20];
    int  points , goal , lose , delta , Rank;
};  //_info

int T , n , m;
_info List[30];

inline int max(int a , int b)
{
    if (a > b)
        return a;
    return b;
}   //max

int get_ID(char *str)
{
    for (int i = 0;i < n;i ++)
        if (strcmp(str , List[i].name) == 0)
            return i;
}   //get_ID

int get_len(int num)
{
    if (num == 0) return 1;
    int ans = 0;
    if (num < 0)
        ans ++;
    while (num)
    {
        ans ++;
        num = num / 10;
    }   //
    return ans;
}   //get_len

bool cmp_points(_info a , _info b)
{
    return (a.points > b.points);
}   //cmp_points

bool cmp_delta(_info a , _info b)
{
    return (a.delta > b.delta);
}   //cmp_delta

bool cmp_goal(_info a , _info b)
{
    return (a.goal > b.goal);
}   //cmp_goal

bool cmp_name(_info a , _info b)
{
    if (strcmp(a.name , b.name) < 0)
        return true;
    return false;
}   //cmp_name

void print()
{
    int max_Rank = 4 , max_name = 6 , max_points = 3 , max_goal = 1 , max_lose = 1 , max_delta = 1;

    for (int i = 0;i < n;i ++)
    {
        int len;
        max_name   = max(max_name , strlen(List[i].name));
        max_points = max(max_points , get_len(List[i].points));
        max_goal   = max(max_goal , get_len(List[i].goal));
        max_lose   = max(max_lose , get_len(List[i].lose));
        max_delta  = max(max_delta , get_len(List[i].delta));
    }

    int sum;
    sum = max_Rank + max_name + max_points + max_goal + max_lose + max_delta + 12 + 5;
    printf("+");
    for (int i = 0;i < sum;i ++)    printf("-");
    printf("+\n");
    //      Row 1

    printf("| Rank |");
    for (int i = 0;i < (max_name - 4) / 2;i ++)     printf(" ");
    printf("Player");
    for (int i = 0;i < (max_name - 3) / 2;i ++)     printf(" ");
    printf("|");
    for (int i = 0;i < (max_points - 1) / 2;i ++)   printf(" ");
    printf("Pts");
    for (int i = 0;i < (max_points ) / 2;i ++)      printf(" ");
    printf("|");
    for (int i = 0;i < (max_goal + 1) / 2;i ++)     printf(" ");
    printf("G");
    for (int i = 0;i < (max_goal + 2) / 2;i ++)     printf(" ");
    printf("|");
    for (int i = 0;i < (max_lose + 1) / 2;i ++)     printf(" ");
    printf("L");
    for (int i = 0;i < (max_lose + 2) / 2;i ++)     printf(" ");
    printf("|");
    for (int i = 0;i < (max_delta + 1) / 2;i ++)    printf(" ");
    printf("D");
    for (int i = 0;i < (max_delta + 2) / 2;i ++)    printf(" ");
    printf("|\n");
    //      Row 2

    for (int i = 0;i < n;i ++)
    {
        printf("|");
        for (int j = 0;j < max_Rank + 2;j ++)           printf("-");
        printf("|");
        for (int j = 0;j < max_name + 2;j ++)           printf("-");
        printf("|");
        for (int j = 0;j < max_points + 2;j ++)         printf("-");
        printf("|");
        for (int j = 0;j < max_goal + 2;j ++)           printf("-");
        printf("|");
        for (int j = 0;j < max_lose + 2;j ++)           printf("-");
        printf("|");
        for (int j = 0;j < max_delta + 2;j ++)          printf("-");
        printf("|\n");

        printf("|");
        for (int j = 0;j < (4 + 2 - get_len(List[i].Rank)) / 2;j ++)     printf(" ");
        printf("%d" , List[i].Rank);
        for (int j = 0;j < (4 + 3 - get_len(List[i].Rank)) / 2;j ++)     printf(" ");
        printf("|");
        for (int j = 0;j < (max_name + 2 - strlen(List[i].name)) / 2;j ++)     printf(" ");
        printf("%s" , List[i].name);
        for (int j = 0;j < (max_name + 3 - strlen(List[i].name)) / 2;j ++)     printf(" ");
        printf("|");
        for (int j = 0;j < (max_points + 2 - get_len(List[i].points)) / 2;j ++)     printf(" ");
        printf("%d" , List[i].points);
        for (int j = 0;j < (max_points + 3 - get_len(List[i].points)) / 2;j ++)     printf(" ");
        printf("|");
        for (int j = 0;j < (max_goal + 2 - get_len(List[i].goal)) / 2;j ++)     printf(" ");
        printf("%d" , List[i].goal);
        for (int j = 0;j < (max_goal + 3 - get_len(List[i].goal)) / 2;j ++)     printf(" ");
        printf("|");
        for (int j = 0;j < (max_lose + 2 - get_len(List[i].lose)) / 2;j ++)     printf(" ");
        printf("%d" , List[i].lose);
        for (int j = 0;j < (max_lose + 3 - get_len(List[i].lose)) / 2;j ++)     printf(" ");
        printf("|");
        for (int j = 0;j < (max_delta + 2 - get_len(List[i].delta)) / 2;j ++)     printf(" ");
        printf("%d" , List[i].delta);
        for (int j = 0;j < (max_delta + 3 - get_len(List[i].delta)) / 2;j ++)     printf(" ");
        printf("|\n");

    }   //  The Players Info

    printf("|");
    for (int j = 0;j < max_Rank + 2;j ++)           printf("-");
    printf("|");
    for (int j = 0;j < max_name + 2;j ++)           printf("-");
    printf("|");
    for (int j = 0;j < max_points + 2;j ++)         printf("-");
    printf("|");
    for (int j = 0;j < max_goal + 2;j ++)           printf("-");
    printf("|");
    for (int j = 0;j < max_lose + 2;j ++)           printf("-");
    printf("|");
    for (int j = 0;j < max_delta + 2;j ++)          printf("-");
    printf("|\n");

    printf("\n");
}   //print

int main()
{
    //freopen(output , "w" , stdout);
    char ch;

    scanf("%d" , &T);
    for (int i = 0;i < T;i ++)
    {
        memset(List , 0 , sizeof(List));
        scanf("%d%d" , &n , &m);
        scanf("%c" , &ch);           //  read '\n'
        for (int i = 0;i < n;i ++)
        {
            scanf("%s" , List[i].name);
            scanf("%c" , &ch);      //  read '\n'
        }   //for i _ n
        for (int i = 0;i < m;i ++)
        {
            char name_1[20] , name_2[20];
            int  goal_1 , goal_2;
            scanf("%s" , name_1);   scanf("%c" , &ch);
            scanf("%d" , &goal_1);
            scanf("%c%c%c" , &ch , &ch , &ch);
            scanf("%d" , &goal_2);
            scanf("%s" , name_2);

            //deal the data
            int u = get_ID(name_1);
            int v = get_ID(name_2);

            List[u].goal += goal_1;     List[u].lose += goal_2;
            List[v].goal += goal_2;     List[v].lose += goal_1;
            if (goal_1 > goal_2)
                List[u].points += 3;
            else if (goal_1 < goal_2)
                List[v].points += 3;
            else
            {
                List[u].points ++;      List[v].points ++;
            }
        }   //for i _ m

        for (int i = 0;i < n;i ++)
            List[i].delta = List[i].goal - List[i].lose;

        sort(List , List + n , cmp_points);

        int j;
        for (int i = 0;i < n - 1;i += j - i)
        {
            for (j = i + 1;j <= n && List[j].points == List[i].points;j ++) {}
            if (j > n)
                j = n;
            sort(List + i , List + j , cmp_delta);
        }   //for i _ j     delta

        for (int i = 0;i < n - 1;i += j - i)
        {
            for (j = i + 1;j <= n && List[j].points == List[i].points
                                  && List[j].delta  == List[i].delta ;j ++)  {}
            if (j > n)
                j = n;
            sort(List + i , List + j , cmp_goal);
        }   //for i _ j     goal

        //detemine the ranks
        List[0].Rank = 1;
        for (int i = 1;i < n;i ++)
            if (List[i].points == List[i - 1].points
             && List[i].delta  == List[i - 1].delta
             && List[i].goal   == List[i - 1].goal)
                List[i].Rank = List[i - 1].Rank;
            else
                List[i].Rank = i + 1;

        for (int i = 0;i < n - 1;i += j - i)
        {
            for (j = i + 1;j <= n && List[j].points == List[i].points
                                  && List[j].delta  == List[i].delta
                                  && List[j].goal   == List[i].goal  ;j ++)  {}
            if (j > n)
                j = n;
            sort(List + i , List + j , cmp_name);
        }   //for i _ j     name

        print();

    }   //for i _ T

    //fclose(stdout);
    return 0;
}   //main

至于Problem B。。。水平有限,还没想出来,之后补充。。。Orz 做出来的人。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:7038次
    • 积分:193
    • 等级:
    • 排名:千里之外
    • 原创:11篇
    • 转载:1篇
    • 译文:0篇
    • 评论:0条
    文章分类