USACO Friday the Thirteenth (Ad Hoc Problems)

题目大意:统计从1900年1月1号开始的n年时间内,每个月的13号落在星期一、星期二、星期三……星期日的次数。

分析:从今年某个月的13号到明年那个月的13号经过的时间恰好是一年,经过的天数可能是365或366,从今年的1月13到明年的1月13经过的天数是由今年的二月份的天数决定的,也就是由今年是否是闰年决定的,2月也是一样,但从今年的3月13到明年的3月13经过的天数是由明年的二月份的天数决定的,也即由明年是否是闰年决定,4、5、6、……12月也一样。

365%7=1

366%7=2

知道了以上2个算式,便可以从今年每月13的星期数推得明年的每月13的星期数,以后n年的都可以推出。递推的初始边界为1900年每月13的星期数,可由题中信息得出,也可查阅日历……

View Code
/*
ID: lijian42
LANG: C++
TASK: friday
*/
#include <stdio.h>
#include <string.h>
int d[12];
int cnt[7];
void init()
{
    d[0]=6;  d[1]=2;  d[2]=2;  d[3]=5;
    d[4]=0;  d[5]=3;  d[6]=5;  d[7]=1;
    d[8]=4;  d[9]=6;  d[10]=2;  d[11]=4;
}
bool IsLeap(int k)
{
    if(k%400==0 || k%4==0 && k%100!=0)   return true;
    return false;
}
void tran(int k)
{
    if(IsLeap(k))   for(int i=0;i<2;i++)   d[i]=(d[i]+1)%7;
    if(IsLeap(k+1)) for(int i=2;i<12;i++)   d[i]=(d[i]+1)%7;
    for(int i=0;i<12;i++)   d[i]=(d[i]+1)%7;
}
int main()
{
    freopen("friday.in","r",stdin);
    freopen("friday.out","w",stdout);
    int n,i,j;
    int test=0;
    while(~scanf("%d",&n))
    {
        memset(cnt,0,sizeof(cnt));
        init();
        for(i=0;i<n;i++)
        {
            for(j=0;j<12;j++)   cnt[d[j]]++;
            tran(1900+i);
        }
        printf("%d",cnt[6],cnt[0]);
        for(i=0;i<6;i++)    printf(" %d",cnt[i]);puts("");
    }
    return 0;
}

 

posted @ 2012-07-20 22:40  BeatLJ  阅读(244)  评论(0编辑  收藏  举报