USACO-Chapter1-Section 1.1-Friday the Thirteenth (friday)

【题目描述】     

      13号又是一个星期五。13号在星期五比在其他日子少吗?为了回答这个问题,写一个程序,要求计算每个月的十三号落在周一到周日的次数。给出N年的一个周期,要求计算1900年1月1日至1900+N-1年12月31日中十三号落在周一到周日的次数,N为正整数且不大于400.

这里有一些你要知道的:

1、1900年1月1日是星期一.

2、4,6,11和9月有30天.其他月份除了2月都有31天.闰年2月有29天,平年2月有28天.

3、年份可以被4整除的为闰年(1992=4*498 所以 1992年是闰年,但是1990年不是闰年).

4、以上规则不适合于世纪年。可以被400整除的世纪年为闰年,否则为平年。所以,1700,1800,1900和2100年是平年,而2000年是闰年.

【输入格式】

      一个正整数n.

【输出格式】

      七个在一行且相分开的整数,它们代表13日是星期六,星期日,星期一...星期五的次数.

【输入样例】

20

【输出样例】

36 33 34 33 35 35 34

【思路】

一(模拟法)

      按月为单位,模拟,1900年1月13日是星期六,那么下一个13日的星期就是(b[i]+13) mod 7,b[i]∈(31,28(29),31,30,……)。这里数据较弱,可以AC,但是当数据BT了,怎么办?这里推荐个按照年计算的方法。当数据比较大时,可以以年为单位计算,每年为365天,mod 7的余数是1,就是说每过一年所有的日和星期错一天,闰年第1、2月错1天,3月以后错2天。这样,只要先求出第一年的解,错位添加到以后的年即可。

二(公式法)

      看到NOCOW上有神牛贴出来蔡勒公式,MS是个计算星期几的公式,很牛X。我把它贴出来大家看下。

  • 蔡勒公式是一种计算任何一日属一星期中哪一日的算法,由蔡勒(Julius Christian Johannes Zeller)推算出。Image:蔡勒公式.png
    公式都是基于公历的置闰规则来考虑。
    公式中的符号含义如下:
  • w:星期
  • c:世纪(前两位数)
  • y:年(后两位数)
  • m:月(m 的取值范围为 3 至 14,即在蔡勒公式中,某年的 1、2月要看作上一年的 13、14月来计算,比如2003年1月1日要看作2002年的13月1日来计算)
  • d:日
  • [ ]:称作高斯符号,代表取整,即只要整数部份。
  • mod:‎‎同余‎(这里代表括号里的答案除以 7 后的余数)(请注意前面是负数取模的情况,取模只可以是正数)若要计算的日期是在1582年10月4日或之前,公式则为
    Image:蔡勒公式_before_15821004.png(因罗马教皇修改历法,把1582年10月4日的下一天改为1582年10月15日)

※。3200不是闰年,详见WIKI。

【代码】

一、模拟法

  • Executing...
  • Test 1: TEST OK [0.000 secs, 276 KB]
  • Test 2: TEST OK [0.000 secs, 276 KB]
  • Test 3: TEST OK [0.000 secs, 276 KB]
  • Test 4: TEST OK [0.000 secs, 276 KB]
  • Test 5: TEST OK [0.000 secs, 276 KB]
  • Test 6: TEST OK [0.000 secs, 276 KB]
  • Test 7: TEST OK [0.000 secs, 276 KB]
  • Test 8: TEST OK [0.000 secs, 276 KB]
  • All tests OK.
{
 ID  : c_CaM.19
 LANG: PASCAL
 TASK: friday
}
Program CaM(input,output);
Var
  i,j,t,n:longint;
  a,b:array[0..13] of longint;

Procedure innt;
Begin
  assign(input,'friday.in'); reset(input);
  assign(output,'friday.out'); rewrite(output);
End;

Procedure outt;
Begin
  close(input);
  close(output);
End;

Begin
  innt;

  a[1]:=31; a[3]:=31; a[5]:=31; a[7]:=31;
  a[8]:=31; a[10]:=31; a[12]:=31;
  a[4]:=30; a[6]:=30; a[9]:=30; a[11]:=30;
  readln(n); t:=0;
  for i:=1900 to 1900+n-1 do
  Begin
    if (i mod 400=0)or((i mod 4=0)and(i mod 100<>0)) then a[2]:=29
    else a[2]:=28;
    for j:=1 to 12 do
    Begin
      inc(b[(t+13)mod 7]);
      inc(t,a[j]);
    End;
  End;
  writeln(b[6],' ',b[0],' ',b[1],' ',b[2],' ',b[3],' ',b[4],' ',b[5]);

  outt;
End.

二、公式法(非笔者)

{根据蔡勒公式写的代码。
ID: Boolean93
PROG: friday
LANG: PASCAL
}
var
 n,i,j,year,m,c,y,w   :longint;
 a                    :array[0..6] of longint;
begin
 Assign(input,'Friday.in');reset(input);
 Assign(output,'Friday.out');rewrite(output);
 
  readln(n);
  for i:=1900 to 1899+n do
    for j:=1 to 12 do
      begin
        year:=i;
        m:=j;
        if (m=1)or(m=2) then
         begin
          dec(year);
          m:=m+12;
         end;
        c:=year div 100;
        y:=year mod 100;
        w:=(y+ y div 4 + c div 4 -2*c+ 26*(m+1) div 10 +13 -1) mod 7;
        w:=(w+7) mod 7;
        inc(a[w]);
      end;
  writeln(a[6],' ',a[0],' ',a[1],' ',a[2],' ',a[3],' ',a[4],' ',a[5]);
 
 Close(input);close(output);
 halt;
end.
posted @ 2012-02-12 12:24  你滴韩王  阅读(355)  评论(0)    收藏  举报