【题解】#373. 「USACO1.1」Friday the Thirteenth 题解(2023-07-19更新)

szyy / 2023-08-17 / 原文

#373. 「USACO1.1」Friday the Thirteenth 题解

本文章的访问次数为

Part 1 提示

题目传送门

  • 欢迎大家指出错误并私信这个蒟蒻
  • 欢迎大家在下方评论区写出自己的疑问(记得 @ 这个蒟蒻)

Part 2 背景

这个蒟蒻又一次写了一篇大水题的题解 (话说为什么是又) ,当然也是为了纪念他的 \(200\) AC。

Part 3 更新日志

  • 2023-02-01 17:20 文章完成
  • 2023-02-02 17:50 提交审核
  • 2023-02-03 18:50 文章审核通过
  • 2023-02-03 19:17 修改了注释
  • 2023-05-25 20:25 修改了 \(\LaTeX\)
  • 2023-05-25 20:32 再次修改了 \(\LaTeX\),感谢 ACRUSHj 提出错误
  • 2023-07-01 15:55 修改了代码
  • 2023-07-12 14:40 将代码转换为图片形式
  • 2023-07-19 20:50 更改了文章格式,使文章看起来更加美观

Part 4 题目知识点

模拟 + 数学

Part 5 题意说明

这道题的要求其实就是写一个程序来计算在 \(n\) 年里 \(13\) 日在星期一,星期二 \(\cdots\) 星期日的次数。这个测试从 \(1900\)\(1\)\(1\) 日到 \(1900+n-1\)\(12\)\(31\) 日。\(n\) 是一个非负数且不大于 \(400\) 。请不要预先算好数据 !
很明显,这道题会考察到和年份有关的知识点,总结一下就是四年一闰,百年不闰,四百年又闰。(不会的话自己去问小学老师,你的小学老师肯定不会怀疑你是不是他教的

Part 6 代码

// #373. 「USACO1.1」Friday the Thirteenth
// code by:st20250113
#include <bits/stdc++.h>

using namespace std;

int a[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, b[8]; // a数组预处理每月天数,b数组用来存储答案

int main()
{
    int n, c = 0;
    scanf("%d", &n);
    for (int i = 1900; i < 1900 + n; i++)
    {
        int f = 0; // 闰年标记
        if ((i % 4 == 0) && (i % 100) || (i % 400 == 0))
        {
            f = 1; // 判断是否为闰年,若成立则f赋值为真
        }
        for (int j = 1; j <= 12; j++)
        {
            int e = 0; // 如果为闰年,2月就要多一天,e在闰年情况下使2月的循环变量增大1
            if (f && j == 2)
            {
                e = 1;
            }
            for (int k = 1; k <= a[j] + e; k++) // k循环日期,m[j]即j月的天数
            {
                c++; // st每天增加
                if (k == 13)
                {
                    b[c % 7]++;
                }
            }
            if (e == 1)
            {
                e = 0; // 2月用过后要清零
            }
        }
    }
    cout << b[6] << " " << b[0] << " " << b[1] << " " << b[2] << " " << b[3] << " " << b[4] << " " << b[5]; // 输出顺序是Sat Sun Mon Tue Wed Thu Fri
    return 0;
}