兰州大学第一届『飞马杯』程序设计竞赛(同步赛)

2021-05-29 12:00 至 2021-05-29 17:00
时长: 5小时

已有1553人报名

比赛说明

比赛名称:兰州大学第一届“飞马杯”程序设计竞赛(同步赛)
比赛时间:2021 年 05 月 29 日,12:00 - 17:00(5 小时)
比赛规则:ACM (个人赛)

编程语言:C/C++,Java,Python
题目数量:12
题目语言:中文
比赛封榜:比赛结束前 1 小时
知乎评价:https://www.zhihu.com/question/460619805

★比赛简介

为了响应教育部提出“新工科”教育战略,培养和展示我校大学生分析、解决问题和计算机编程的能力,鼓励和培养创新思维,丰富校园学术气氛,造就具有综合素质的面向 21 世纪的计算机人才,兰州大学将于 2021 年 05 月 29 日举办兰州大学第一届“飞马杯”程序设计竞赛,面向兰州大学全体学生,同时我们也由衷地欢迎来自全国各地的同学参加。

比赛开始时会同时发布 PDF 题面,比赛结束时会发布 PDF 题解以及标程和测试数据。
(感谢牛客网提供的技术支持)


★组织机构★

主办:兰州大学 ICPC 程序设计集训队、兰州大学算法与程序设计协会
指导教师:马俊、程建军、燕昊、火克华

★比赛奖品★

排名前 3 的参赛者直接获得 公仔 ★ 1
其余凡过题的参赛者,随机抽取 12 人,每人发放 公仔 1

采用以下代码计算获奖序列字符串的 SHA2560xAE58CD42462255AED377B1F8D57088FE8BEC789D0CD3E32032348E3B3796A16C,其中 “” 赛后公开,其中包含 12 个已生成的随机数,逐个对有效参赛人数取模后加 1,得到获奖排名。
若有重复获奖者,按排名向后顺延。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void SHA_256(unsigned char*, const unsigned char*, size_t);

int main()
{
    const char* awarded = "LZU-FeiMa: { ★★ }";
    unsigned char hash[0x20];

    SHA_256(hash, (unsigned char*)awarded, strlen(awarded));

    printf("0x");
    for (size_t i = 0; i != 0x20; ++i) {
        printf("%02X", hash[i]);
    }

    return 0;
}

#define ROTATE_RIGHT(value, distance) (((value) >> (distance)) | ((value) << (0x20 - (distance))))

unsigned int bigEndianConversion(unsigned int originalValue, size_t length) {

    if (!length) {
        return originalValue & 0xFF;
    }
    return ((originalValue & 0xFF) << (length * 0x08)) | bigEndianConversion(originalValue >> 0x08, length - 0x01);
}

#define BIG_ENDIAN_CONVERSION(originalValue) (bigEndianConversion((originalValue), sizeof(unsigned int) - 0x01))

const unsigned int initializationVector[] = {
    0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,
    0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19
};

const unsigned int roundConstants[] = {
    0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
    0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
    0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
    0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
    0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
    0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
    0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
    0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
};

void SHA_256(unsigned char* result, const unsigned char* text, size_t length) {

    unsigned char block[0x40];
    size_t round, i;
    unsigned int vector[0x08], word[0x40], j, k;

    memcpy(result, initializationVector, 0x20);

    for (round = 0; round <= (length + 0x08) / 0x40; ++round) {

        if (round * 0x40 <= length) {
            memcpy(block, text + round * 0x40, (round * 0x40 + 0x40 <= length ? 0x40 : length - round * 0x40));
        }
        if (round * 0x40 + 0x40 > length) {
            if (round * 0x40 <= length) {
                block[length - round * 0x40] = 0x80;
                memset(block + length - round * 0x40 + 0x01, 0x00, round * 0x40 + 0x3F - length);
            }
            else {
                memset(block, 0x00, 0x38);
            }
            if (round == (length + 0x08) / 0x40) {
                for (i = 0; i != 0x08; ++i) {
                    block[i + 0x38] = (((unsigned long long)length * 0x08) >> (0x38 - i * 0x08)) & 0xFF;
                }
            }
        }

        for (i = 0; i != 0x10; ++i) {
            word[i] = BIG_ENDIAN_CONVERSION(*(unsigned int*)(block + i * 0x04));
        }
        for (; i != 0x40; ++i) {
            word[i] = word[i - 0x10] + word[i - 0x07];
            word[i] += (word[i - 0x0F] >> 0x03) ^ ROTATE_RIGHT(word[i - 0x0F], 0x07) ^ ROTATE_RIGHT(word[i - 0x0F], 0x12);
            word[i] += (word[i - 0x02] >> 0x0A) ^ ROTATE_RIGHT(word[i - 0x02], 0x11) ^ ROTATE_RIGHT(word[i - 0x02], 0x13);
        }

        memcpy(vector, result, 0x20);

        for (i = 0; i != 0x40; ++i) {
            j = ROTATE_RIGHT(vector[0x00], 0x02) ^ ROTATE_RIGHT(vector[0x00], 0x0D) ^ ROTATE_RIGHT(vector[0x00], 0x16);
            j += (vector[0x00] & vector[0x01]) ^ (vector[0x00] & vector[0x02]) ^ (vector[0x01] & vector[0x02]);
            k = vector[0x07] + word[i] + roundConstants[i];
            k += ROTATE_RIGHT(vector[0x04], 0x06) ^ ROTATE_RIGHT(vector[0x04], 0x0B) ^ ROTATE_RIGHT(vector[0x04], 0x19);
            k += (vector[0x04] & vector[0x05]) ^ (~vector[0x04] & vector[0x06]);
            j += k;
            k += vector[0x03];
            memmove(vector + 0x01, vector, 0x1C);
            vector[0x00] = j;
            vector[0x04] = k;
        }

        for (i = 0; i != 0x08; ++i) {
            *(unsigned int*)(result + i * 0x04) += vector[i];
        }
    }

    for (i = 0; i != 0x08; ++i) {
        *(unsigned int*)(result + i * 0x04) = BIG_ENDIAN_CONVERSION(*(unsigned int*)(result + i * 0x04));
    }
}