usaco/1.1 Friday the Thirteenth

题目:http://cerberus.delos.com:790/usacoprob2?a=u6HWJikTmqd&S=friday

代码:

/*
ID: chicc991
PROG: friday
LANG: C++
*/
#include <fstream>
using namespace std;

int n;//输入的年份
int s[7];

void calculate()
{
    int i,w,y,c;

    for(i=0; i<=n-1; i++)
    {
        int m,k;
        int d=13;//日期
        y=(1900+i)%100;//年份后两位
        c=(1900+i)/100;//年份前两位
        if(i==(n-1)) k=12;
        else k=14;
        for(m=3; m<=k; m++) //月份由1-12变为3-14
        {
            w=y+int(y/4)+int(c/4)-2*c+int(26*(m+1)/10)+d-1;
            w=(w%7+7)%7;
            s[w]++;
        }
    }

    w=99+99/4+18/4-2*18+26*(13+1)/10+13-1;
    w=(w%7+7)%7;
    s[w]++;

    w=99+99/4+18/4-2*18+26*(14+1)/10+13-1;
    w=(w%7+7)%7;;
    s[w]++;

}
int main()
{
    ifstream fin("friday.in");
    ofstream fout("friday.out");

    fin>>n;

    int j;
    for(j=0; j<7; j++)
        s[j]=0;
    calculate();
    fout<<s[6]<<" ";
    for(j=0; j<5; j++)
        fout<<s[j]<<" ";
        fout<<s[5]<<endl;//为了输出格式一致
        fin.close();
        fout.close();

}

1.

蔡勒公式 自行查看百度百科
2.整数取模(以模7为例)
w=(w%7+7)%7

如果改为负数时w=w%7+7,则-7,-14等情况将会被忽略。


不用蔡勒公式解法:

分析:

  • 因为1900.1.1是星期一,所以1900.1.13就等于(13-1) mod7+1=星期六。这样讲可能不太清楚。那么,我来解释一下:每过7天是一个星期。n天后是星期几怎么算呢?现在假设n是7的倍数,如果n为14,那么刚好就过了两个星期,所以14天后仍然是星期一。但如果是过了15天,那么推算就得到是星期二。这样,我们就可以推导出一个公式来计算。(n天 mod 7(一个星期的天数)+ 现在日期的代号) mod 7 就等于现在日期的代号。当括号内的值为7的倍数时,其代号就为0,那么,此时就应该是星期日这样,我们可以得出题目的算法:

int a[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}
int b[8]={0}
a数组保存一年12个月的天数(因为C语言中数组起始下标为0,所以这里定义为13)。
b数组保存星期一到星期日出现的天数。用date记录目前是星期几的代号,然后用两个循环,依次加上所经过的月份的天数,就出那个月是星期几,当然,要注意判断闰年!知道了这个方法,实现起来就很容易了。
注意考虑闰月的情况。
最后注意要换行,否则会错误。


代码:

 
#include<fstream>
using namespace std;
 
int main()
{
	int year,month,i,n,last=3;   
	int dayOfMonth[12]={31,31,28,31,30,31,30,31,31,30,31,30};    
	int result[7]={0};          
	ifstream fin("friday.in");
	ofstream fout("friday.out");
 
	fin>>n;
 
	for(year=1900;year<1900+n;++year){
		if(year%400==0||(year%100!=0&&year%4==0)) dayOfMonth[2]=29;
		for(month=0;month<12;++month){
			last=(last+dayOfMonth[month])%7;
			result[last]++;
		}
		dayOfMonth[2]=28;
	}
 
	for(i=0;i<6;++i) fout<<result[(i+6)%7]<<' ';
	fout<<result[5]<<endl;
 
	fin.close();
	fout.close();
 
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值