1. 程式人生 > >CODE【VS】1384 黑色星期五(計算某一天是星期幾的公式)

CODE【VS】1384 黑色星期五(計算某一天是星期幾的公式)

題目描述 Description

13號又是星期五是一個不尋常的日子嗎?
13號在星期五比在其他日少嗎?為了回答這個問題,寫一個程式來計算在n年裡13
日落在星期一,星期二......星期日的次數.這個測試從1900年1月1日到
1900+n-1年12月31日.n是一個非負數且不大於400.
這裡有一些你要知道的:

1900年1月1日是星期一.
4,6,11和9月有30天.其他月份除了2月有31天.閏年2月有29天,平年2月有28天.
年份可以被4整除的為閏年(1992=4*498 所以 1992年是閏年,但是1990年不是閏年)
以上規則不適合於世紀年.可以被400整除的世紀年為閏年,否則為平年.所以,1700,1800,1900和2100年是平年,而2000年是閏年.

請不要預先算好資料!

輸入描述 Input Description

一個整數n.

輸出描述 Output Description

七個在一行且相分開的整數,它們代表13日是星期六,星期日,星期一.....星期五的次數.

樣例輸入 Sample Input

20

樣例輸出 Sample Output

36 33 34 33 35 35 34

資料範圍及提示 Data Size & Hint

n是一個非負數且不大於400.

題解:這道題的話,我感覺直接從1900年到給定的那個年份跑一遍,暴力可以求出來。應該不會超時。這裡我用的不是暴力。

   是一個叫基姆拉爾森計算公式:W = (d+2*m+3*(m+1)/5+(y)+(y)/4-(y)/100+(y)/400)%7; 在公式中d表示日期中的日數+1,m表示月份數,y表示年份。 

注意:用該公式時,需要把一月和二月看成是上一年的十三月和十四月,公式中的d是日期加1.所以計算結果就是實際的星期,即是:“1”為星期一,“2”為星期二。。。。“0”為星期日。

    還有另外一個公式:W = (d+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7 (其中y是四位數的,如2009。)

注意:該公式中同樣要把1月和2月分別當成上一年的13月和14月處理。而且該公式的“0”為星期一,。。。。,“6”為星期日。

附上程式碼:

#include<cstdio>
#include<cstring>
#include<cmath>
#include<climits>
#include<iostream>
#include<algorithm>
#include<vector>
#include<string>
#include<map>
#include<queue>
#include<stack>
using namespace std;
int main()
{
    int n;
    scanf("%d", &n);
    int week[10] = {0};
    for(int i = 1900; i < 1900+n; i++)
    {
        for(int j = 1; j < 13; j++)
        {
            int m, W;
            if(j == 1 || j == 2)
            {
                m = j+12;
                W = (14+2*m+3*(m+1)/5+(i-1)+(i-1)/4-(i-1)/100+(i-1)/400)%7; // 基姆拉爾森計算公式
            }
            else
            {
                m = j;
                W = (14+2*m+3*(m+1)/5+(i)+(i)/4-(i)/100+(i)/400)%7; // 基姆拉爾森計算公式
            }
            week[W]++;
        }
    }
    printf("%d %d %d %d %d %d %d\n", week[6], week[0], week[1], week[2], week[3], week[4], week[5]);
    return 0;
}