B.中国人的智慧 | 2018 校内选拔赛

Description

八卦是《易经》的基本概念,可代表一切自然现象的动静状态,每个卦由三个爻组成。“卦”有“悬挂”的意思,也代表将各种现象的标示竖立起来以便于观察。

八卦的项目组合,可代表各种自然现象或动态,分别为“天、地、水、火、雷、风、山、泽”,卦名则称“乾、坤、坎、离、震、巽、艮、兑”。易经的八卦代表了古代中国的天文地理哲学等文化思想,其理论还涉及到武术、中国音乐等方方面面。

若将八卦两两相重,形成六十四卦。原本八卦(三个爻)亦称为八个“单卦”,而相同的两个八卦的组合(六个爻)则称“重卦”。

八卦中有两个符号,一个是“—”,另一个是“- -”。在《易经》中并没有“阴阳”二字,数百年后的《易传》才把“—”叫阳爻,把“- -”叫阴爻。

本题输出中,使用__表示阳爻,使用–表示阴爻。

伏羲先天六十四卦〈方圆四分四层图〉排列方位图表

Trigramme2637 ☷.svg

坤(地)

Trigramme2636 ☶.svg

艮(山)

Trigramme2635 ☵.svg

坎(水)

Trigramme2634 ☴.svg

巽(风)

Trigramme2633 ☳.svg

震(雷)

Trigramme2632 ☲.svg

离(火)

Trigramme2631 ☱.svg

兑(泽)

Trigramme2630 ☰.svg

乾(天)

← 上卦
↓ 下卦
Iching-hexagram-02.svg (1)

坤为地

Iching-hexagram-23.svg (2)

山地剥

Iching-hexagram-08.svg (3)

水地比

Iching-hexagram-20.svg (4)

风地观

Iching-hexagram-16.svg (5)

雷地豫

Iching-hexagram-35.svg (6)

火地晋

Iching-hexagram-45.svg (7)

泽地萃

Iching-hexagram-12.svg (8)

天地否

Trigramme2637 ☷.svg

坤(地)

Iching-hexagram-15.svg (9)

地山谦

Iching-hexagram-52.svg (10)

艮为山

Iching-hexagram-39.svg (11)

水山蹇

Iching-hexagram-53.svg (12)

风山渐

Iching-hexagram-62.svg (13)

雷山小过

Iching-hexagram-56.svg (14)

火山旅

Iching-hexagram-31.svg (15)

泽山咸

Iching-hexagram-33.svg (16)

天山遁

Trigramme2636 ☶.svg

艮(山)

Iching-hexagram-07.svg (17)

地水师

Iching-hexagram-04.svg (18)

山水蒙

Iching-hexagram-29.svg (19)

坎为水

Iching-hexagram-59.svg (20)

风水涣

Iching-hexagram-40.svg (21)

雷水解

Iching-hexagram-64.svg (22)

火水未济

Iching-hexagram-47.svg (23)

泽水困

Iching-hexagram-06.svg (24)

天水讼

Trigramme2635 ☵.svg

坎(水)

Iching-hexagram-46.svg (25)

地风升

Iching-hexagram-18.svg (26)

山风蛊

Iching-hexagram-48.svg (27)

水风井

Iching-hexagram-57.svg (28)

巽为风

Iching-hexagram-32.svg (29)

雷风恒

Iching-hexagram-50.svg (30)

火风鼎

Iching-hexagram-28.svg (31)

泽风大过

Iching-hexagram-44.svg (32)

天风姤

Trigramme2634 ☴.svg

巽(风)

Iching-hexagram-24.svg (33)

地雷复

Iching-hexagram-27.svg (34)

山雷颐

Iching-hexagram-03.svg (35)

水雷屯

Iching-hexagram-42.svg (36)

风雷益

Iching-hexagram-51.svg (37)

震为雷

Iching-hexagram-21.svg (38)

火雷噬嗑

Iching-hexagram-17.svg (39)

泽雷随

Iching-hexagram-25.svg (40)

天雷无妄

Trigramme2633 ☳.svg

震(雷)

Iching-hexagram-36.svg (41)

地火明夷

Iching-hexagram-22.svg (42)

山火贲

Iching-hexagram-63.svg (43)

水火既济

Iching-hexagram-37.svg (44)

风火家人

Iching-hexagram-55.svg (45)

雷火丰

Iching-hexagram-30.svg (46)

离为火

Iching-hexagram-49.svg (47)

泽火革

Iching-hexagram-13.svg (48)

天火同人

Trigramme2632 ☲.svg

离(火)

Iching-hexagram-19.svg (49)

地泽临

Iching-hexagram-41.svg (50)

山泽损

Iching-hexagram-60.svg (51)

水泽节

Iching-hexagram-61.svg (52)

风泽中孚

Iching-hexagram-54.svg (53)

雷泽归妹

Iching-hexagram-38.svg (54)

火泽睽

Iching-hexagram-58.svg (55)

兑为泽

Iching-hexagram-10.svg (56)

天泽履

Trigramme2631 ☱.svg

兑(泽)

Iching-hexagram-11.svg (57)

地天泰

Iching-hexagram-26.svg (58)

山天大畜

Iching-hexagram-05.svg (59)

水天需

Iching-hexagram-09.svg (60)

风天小畜

Iching-hexagram-34.svg (61)

雷天大壮

Iching-hexagram-14.svg (62)

火天大有

Iching-hexagram-43.svg (63)

泽天夬

Iching-hexagram-01.svg (64)

乾为天

Trigramme2630 ☰.svg

乾(天)

Input

第一行为一个不大于 64 的正整数 T,其后 T 行
每行为一个不大于 64 的正整数

Output

对于输入的第一行之后的每一行,输出该正整数在伏羲先天六十四卦卦象演化序号中所对应的卦象,若需输出多个卦象,则在两个卦象中间空一行。

Sample Input

2
20
21

Sample Output

__
__
--
--
__
--

--
--
__
--
__
--

Hint

签到题,通过卦象来表示二进制数值。

题解

#include "bits/stdc++.h"
int main()
{
    int T;
    scanf("%d", &T);
    for (int i = 0; i < T; i++)
    {
        int n;
        scanf("%d", &n);
        n--;
        bool arr[6];
        memset(arr, 0, sizeof(arr));
        for (int j = 0; j < 6; j++)
        {
            arr[j] = n / (int)pow(2, (5 - j));
            n %= (int)pow(2, (5 - j));
        }
        for (int j = 5; j >= 0; j--)
            printf(arr[j] ? "__\n" : "--\n");
        putchar('\n');
    }

    return 0;
}

E.今天也是元气满满的一天 | 2018 校内选拔赛 预选赛 Day2

Description

我们使用格式 YYYYMMDD 表示一个日期
显然,一个日期由 8 个 0 ~ 9 之间的数码组成
在这 8 个数码组成的数列中
如果有连续 3 个或以上的数码可以构成等差数列

等差数列(又名算术数列)是数列的一种。在等差数列中,任何相邻两项的差相等。该差值称为公差。例如数列 3, 5, 7, 9, 11, 13 就是一个等差数列。 在这个数列中,从第二项起,每项与其前一项之差都等于2,即公差为2。
Sigler, Laurence E. (trans.). Fibonacci’s Liber Abaci.
Springer-Verlag. 2002: 259–260. ISBN 978-0-387-95419-6.

那么这个日期将无法成为密码
请你找出无法成为密码的日期有多少

Input

两行
第一行是开始日期
第二行是结束日期
日期使用格式 YYYYMMDD 表示,且均不在 1900 年 1 月 1 日之前,均不在 2999 年 12 月 31 日之后
保证结束日期不在开始日期之前

Output

一个数字
表示从开始日期到结束日期的日期范围(包括开始日期和结束日期)内,有多少个日期无法成为密码

Sample Input

19980327
19980806

Sample Output

3

Hint

暴力。

题解

// #define debug
#include "bits/stdc++.h"
using namespace std;
inline int query_days_for_year(int y)
{
    return (y % 400 == 0|| (y % 4 == 0 && y % 100 != 0)) ? 366 : 365;
}
int mo[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
inline int query_days_for_month(int m, int y)
{
    //特别注意
    if (m != 2)
        return mo[m];
    else
        if (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0))
            return 29;
        else
            return 28;
}
inline bool chk(char A[], char B[])//替代strcmp
{
    for (int i = 0; i < 8; i++)
        if (A[i] != B[i])
            return 0;
    return 1;
}
inline int tran(int y, int m, int d, char str[])
{
    // #ifdef debug
    // printf("y m d %d %d %d\n", y, m, d);
    // #endif
    if (d > query_days_for_month(m, y))
    {
        d = 1;
        m++;
        #ifdef debug
        printf("m++\n");
        #endif
        if (m > 12)
        {
            m = 1;
            y++;
            #ifdef debug
            printf("y++\n");
            #endif
        }
    }
    str[0] = y / 1000;
    str[1] = y % 1000 / 100;
    str[2] = y % 100 / 10;
    str[3] = y % 10;

    str[4] = m / 10;
    str[5] = m % 10;

    str[6] = d / 10;
    str[7] = d % 10;
    return y*10000 + m*100 + d;
}
int main()
{
    int y1, m1, d1, y2, m2, d2;
    char str1[9], str2[9];
    scanf("%s%s", str1, str2);
    for (int i = 0; i < 8; i++)
    {
        str1[i] -= '0';
        str2[i] -= '0';
    }
    y2 = str2[0]*1000 + str2[1]*100 + str2[2]*10 + str2[3];
    m2 = str2[4]*10 + str2[5];
    d2 = str2[6]*10 + str2[7];

    int sum = 0;
    y1 = str1[0]*1000 + str1[1]*100 + str1[2]*10 + str1[3];
    m1 = str1[4]*10 + str1[5];
    d1 = str1[6]*10 + str1[7];
    while (1)
    {
        for (int i = 0; i < 6; i++)
            if (str1[i+1] - str1[i] == str1[i+2] - str1[i+1])
            {
                sum++;
                break;
            }

        if (chk(str1, str2))
        {
            printf("%d\n", sum);
            return 0;
        }
        //自增
        d1++;
        y1 = tran(y1, m1, d1, str1);
        m1 = (y1 % 10000) / 100;
        d1 = y1 % 100;
        y1 /= 10000;
        #ifdef debug
        printf("p1 %d %d %d\n", y1, m1, d1);
        #endif
    }

    return 0;
}

[1001]最长的区段 | 我们的源代码

Description

现在有一个有n(1<=n<=100000)个正整数的数列ai(1<=ai<=32768), 请你从中找出最长的一段连续序列,使得这段序列中所有元素的和不超过k(1<=k<=109)。输出最长的长度。

Input

输入包含多组样例。
每组样例包含两行,其中第一行包含两个整数n和k,第二行包含n个整数ai。
当接收到n=k=0时输入结束,两个0是结束标记,不是一组测试样例。

Output

对于每组样例,输出一行,包含一个整数,代表最长的长度。

Sample Input

6 10
3 4 3 2 1 6
0 0

Sample Output

4

Hint

题解

#include "bits/stdc++.h"
using namespace std;
int arr[100010];
int main()
{
    while (1)
    {
        int n, k;
        scanf("%d %d", &n, &k);
        if (n == 0 && k == 0)
            return 0;
        int sum = 0;
        int max = 0;
        int res = 0;
        memset(arr, 0, sizeof(arr));

        for (int i = 0; i < n; i++)
        {
            scanf("%d", &arr[i]);
            sum += arr[i];
            max++;
            while (sum > k)
            {
                max--;
                sum -= arr[i - max];
            }
            if (max > res)
                res = max;
        }
        printf("%d\n", res);
    }
}

D.两情若是久长时 | 2018 校内选拔赛 预选赛 Day1

Description

纤云弄巧,飞星传恨,银汉迢迢暗度。
金风玉露一相逢,便胜却、人间无数。
柔情似水,佳期如梦,忍顾鹊桥归路。
两情若是久长时,又岂在、朝朝暮暮。

聪明的你,请帮助牛郎织女计算距离他们相会还有多少天。

Input

两行,每行为一个日期。
日期的格式是 yyyy-mm-dd
第一个日期代表当前日期
第二个日期代表牛郎织女可以相会的日期
输入保证日期范围在 1900 年 1 月 1 日至 2999 年 12 月 31 日之间

Output

如果牛郎织女可以相会,请输出距离他们相会还有多少天;
如果牛郎织女错过了相会日期,请输出“liang qing ruo shi jiu chang shi you qi zai zhao zhao mu mu”(双引号不输出)

Sample Input

1900-01-01
1900-01-01

Sample Output

0

Hint

将问题转化为计算日期到1900年1月1日的日期差,然后依据两个结果之差的正负性进行判断。

题解

#include "cstdio"
inline int query_days_for_year(int y)
{
    return (y % 400 == 0|| (y % 4 == 0 && y % 100 != 0)) ? 366 : 365;
}
inline int query_days_for_month(int m, int y)
{
    int arr[12] = {31, 31, (y % 400 == 0 || (y % 4 == 0 && y % 100 != 0)) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30};
    return arr[m % 12];
}
int main()
{
    int days[2] = {0, 0};
    for (int T = 0; T < 2; T++)
    {
        int y, m, d;
        scanf("%d-%d-%d", &y, &m, &d);
        int delta_y = y - 1900;
        //add days of complete years
        for (int i = 1900; i < y; i++)
            days[T] += query_days_for_year(i);
        //add days of complete months
        for (int i = 1; i < m; i++)
            days[T] += query_days_for_month(i, y);
        //add days of days
        days[T] += d;
    }

    int res = days[1] - days[0];
    if (res >= 0)
        printf("%d\n", res);
    else
        printf("liang qing ruo shi jiu chang shi you qi zai zhao zhao mu mu\n");
    return 0;
}

B.小Z来讲排名规则 | 2018 校内选拔赛 练习赛

Description

本次比赛严格按照ACM的排名规则进行,但可能很多小伙伴并不太了解这个排名方法,今天小Z来给大家简单说明一下。每个人的排名根据他解出的题目数量、做题时间还有错误提交次数决定,呃。。。在某些特殊情况下跟大家的昵称也有关系哟~不过不要着急去改昵称,毕竟是特殊情况,很难遇到的。下面我具体说明一下。

  1. 排名的第一关键字是解出的题目数,也就是说,解出题目数量多的小伙伴一定会排在解出题目数量少的小伙伴前面
  2. 如果解出的题目数量相同,则根据“罚时”决定排名,罚时少者靠前。罚时是这样定义的:每道成功解出的题目会造成罚时,其他题目不会;每道成功解出的题目造成的罚时是成功解出该题的时间,加上错误提交次数20分钟(比如一道题目在第30分钟解出,之前错误提交了两次,那么总的罚时就是30+20*2=70分钟,这里的错误指的是除了Accept之外的所有反馈情况);最终的罚时是所有成功解出题目的罚时的总和。

  3. 一道题目正确解出后,再次提交无论结果如何,都不会再对罚时产生任何影响。

  4. 如果解出的题目数量和罚时数量都相同,在这个平台上就会按照昵称排序。

举个例子,比如当前有5道题目,你成功解出了1,3,5号题目,1号题目在第5分钟1次解出,第3号题目在第10分钟尝试了一次但是wa了,在第15分钟解出;第5号题目在第20分钟解出,之后你又提交了2次;第2号题目你尝试了4次但是都没有解出;第4号题目你没有尝试。那么最终你的罚时是5 + 0 + 15+1*20 + 0 + 20 = 60分钟,你解出了3道题。假设此时有另外三个小伙伴A,B,C,成绩分别是4题75分钟,3题90分钟,2题20分钟,那么最终的排名是A,你,B,C。

好了,现在给你一些提交记录,按照这个规则试着计算一下吧。

Input

第一行包含一个整数T,代表数据组数。
接下来包含T组测试数据。
每组数据第一行包含三个整数n,m,q,分别代表参赛人数、题目数量、提交记录数量。(1<=n,m,q<=10)
紧接着q行,每行包含4个整数p,t,r,s,意思是p号小伙伴在第t分钟提交了r号题目,得到了s的反馈,若s==0则代表错误,s==1代表正确。注意,你的编号就是1号。其他编号的小伙伴只是陪你一起打比赛玩耍的~(1<=p<=n,1<=t<=100,1<=r<=m,s=0或者s=1)
输入保证不存在两个选手,其通过题目数量和罚时相同。

Output

对于每组测试样例,输出一行包含三个整数,分别代表你(1号)的排名、做出的题目数量和罚时。

Sample Input

1
2 5 10
1 5 1 1
1 6 2 0
1 7 2 0
1 8 2 0
1 9 2 0
1 10 3 0
1 15 3 1
1 20 5 1
1 30 5 1
1 35 5 0

Sample Output

1 3 60

Hint

通过结构体数组存储数据,使用cmp函数调用sort对结构体数组进行排序。

题解

#define N 20
#include "cstdio"
#include "cstring"
#include "cstdlib"
#include "iostream"
#include "cmath"
#include "algorithm"
using namespace std;

struct Problem
{
    int time[N];//各用户错误次数
}problem[N];

struct Member
{
    int sum;//AC次数
    int time;//罚时
    int num;//编号
}member[N];

/**
 * 排名关键字权重
 * 1. AC个数
 * 2. 罚时 = 解出时间 + 20 * 错误提交个数,只有AC才会计算罚时
 * 3. 昵称(不考虑)
 */

inline bool cmp(Member A, Member B)
{
    //名次从高向低排列
    if (A.sum < B.sum || (A.sum == B.sum && A.time > B.time))
            return 0;
    return 1;
}

int main()
{
    //std::ios_base::sync_with_stdio(false);
    //std::cin.tie(0);
    //srand((unsigned int)(time(NULL)));
    int T;
    scanf("%d", &T);//T组样例
    for (int Case = 0; Case < T; Case++)
    {
        /**
         * n 参赛人数
         * m 题目数量
         * q 提交记录数量
         */
        int n, m, q;
        scanf("%d%d%d", &n, &m, &q);
        //标记编号方便查询自己
        for (int i = 1; i <= n; i++)
            member[i].num = i;

        for (int i = 0; i < q; i++)
        {
            int p, t, r, s;
            /**
             * p 选手id
             * t 解出时间
             * r 题目编号
             * s 返回结果 0 错误 1 正确
             */
            scanf("%d%d%d%d", &p, &t, &r, &s);
            if (s)
            {
                //正确
                //处理多次提交正确结果
                if (problem[r].time[p] != -1)
                {
                    member[p].sum++;
                    member[p].time += t + 20 * problem[r].time[p];
                    problem[r].time[p] = -1;//做标记
                }
            }
            else
            {
                //错误
                //处理做对后故意做错
                if (problem[r].time[p] != -1)
                    problem[r].time[p]++;
            }
        }
        sort(member + 1, member + n + 1, cmp);
        for (int i = 1; i <= n; i++)
        {
            if (member[i].num == 1)
            {
                printf("%d %d %d\n", i, member[i].sum, member[i].time);
                break;
            }
        }
        memset(problem, 0, sizeof(problem));
        memset(member, 0, sizeof(member));
    }
    
    return 0;
}