私は現在USACOサイトで問題(13日の金曜日)に取り組んでおり、数値Nを指定して、1900年1月1日から12月までの各曜日に13日の金曜日が着陸する頻度を計算するプログラムをコーディングしました。 31st、1900 + N-1。アルゴリズムは暗算のトリックから着想を得ています:http ://www.jimloy.com/math/day-week.htm
注意点:1900年1月1日は月曜日でした。30日は、9月、4月、6月、11月で、残りはすべて31です。ただし、2月は28で、うるう年は29です。毎年、4で割り切れるのはうるう年です(1992 = 4 * 498なので、1992うるう年になりますが、1990年はうるう年ではありません)上記の規則は、1世紀の間は当てはまりません。400で割り切れる世紀の年はうるう年ですが、他のすべての年はうるう年ではありません。したがって、1700、1800、1900、および2100世紀はうるう年ではありませんが、2000年はうるう年です。*
プログラムは、N = 256(1900〜2156)の場合を除いて正常に動作します。私のプログラム出力:440 438 439 439 437 439 440
USACOにいる間、次のようになります:440 439 438 438 439 439 439
プログラムは、入力としてNを含むファイル(friday.in)を受け取り、別のファイル(friday.out)の1行に各日(土曜日から開始)の発生数を表す7つのスペース区切りの整数を出力します。
デバッグのためにいくつかのcoutを配置しました。
コードは次のとおりです。
/*
ID: freebie1
PROG:friday
LANG: C++
*/
#include <fstream>
#include <vector>
#include <iostream>
using namespace std;
class Date
{
public:
Date(int month=0,int year=0):m_month(month),m_year(year)
{
}
int monthDiff()
{
if(m_month<=3)
{
if(m_month==1)
{
return 0;
}
else if(m_month==2)
{
return 31;
}
}
if(m_month>=3)
{
if((m_year%4==0 && m_year%100!=0)||(m_year%100==0 && m_year%400==0))
{
if(m_month<9)
{
if(m_month%2==0)
return 60+(31*int(m_month/2.6)+30*(int(m_month/2.6)-1));
else
return 60+(61*int(m_month/3.5));
}
else if(m_month>=9)
{
if(m_month%2==0)
return 91+61*(m_month/3);
else
return 91+(31*int(m_month/2.75)+30*int(m_month/3.6));
}
}
else
{
if(m_month<9)
{
if(m_month%2==0)
return 59+(31*int(m_month/2.6)+30*(int(m_month/2.6)-1));
else
return 59+(61*int(m_month/3.5));
}
else if(m_month>=9)
{
if(m_month%2==0)
return 90+61*(m_month/3);
else
return 90+(31*int(m_month/2.75)+30*int(m_month/3.6));
}
}
}
}
void show()
{
cout<<m_month<<"/"<<m_year<<": ";
}
int tellDay()
{
int daysInYears=int((m_year-1900))*365;
int daysInMonths=this->monthDiff();
int leapDays;
if(m_year%4==0 && m_year!=1900)
leapDays=int((m_year-1900)/4)-1;
else if(m_year>2100)
leapDays=int((m_year-1900)/4)-1;
else if(m_year>2200)
leapDays=int((m_year-1900))/4-2;
else
leapDays=int((m_year-1900))/4;
int days=13+leapDays;
int res=daysInYears+daysInMonths+days;
cout<<"MonthDiff: "<<this->monthDiff()<<" In years: "<<daysInYears<<" days: "<<days<<" ";
return res%7;
}
private:
int m_month;
int m_year;
};
int main()
{
ifstream fin("friday.in");
ofstream fout("friday.out");
if(fin)
{
int n(0),day(0),sMonth(1),sYear(1900);
fin>>n;
vector<int> weekDays(7,0);
for(int i(0);i<n;i++)
{
for(int j(0);j<12;j++)
{
Date date(sMonth+j,sYear+i);
day=date.tellDay();
date.show();
cout<<day<<endl;
switch(day)
{
case 0:
weekDays[1]+=1;
break;
case 1:
weekDays[2]+=1;
break;
case 2:
weekDays[3]+=1;
break;
case 3:
weekDays[4]+=1;
break;
case 4:
weekDays[5]+=1;
break;
case 5:
weekDays[6]+=1;
break;
case 6:
weekDays[0]+=1;
break;
}
}
}
for(int i(0);i<6;i++)
{
fout<<weekDays[i]<<" ";
}
fout<<weekDays[6]<<endl;
}
return 0;
}