[B]Project Euler #19

プロジェクト・オイラー
問題 19

次の情報が与えられている。


  • 1900年1月1日は月曜日である。
  • 9月、4月、6月、11月は30日まであり、2月を除く他の月は31日まである。
  • 2月は28日まであるが、うるう年のときは29日である。
  • うるう年は西暦が4で割り切れる年に起こる。しかし、西暦が400で割り切れず100で割り切れる年はうるう年でない。
  • 20世紀(1901年1月1日から2000年12月31日)で月の初めが日曜日になるのは何回あるか。



今回は比較的簡単。

  • 1900年から、毎月の日数を加算していく。
  • 2月は、西暦から求めたうるう年をさらに加算。
  • 月の日数+1が月初めである。
  • カウント日数を7で割った余りが曜日である。
  • 1900年1月1日(初期値1)は月曜日であるので、日曜日は0となる。
  • 1901年以上で2001年未満のうち、日曜日をカウントしてやる。


/*------------------------------------------------------>
プロジェクト・オイラー
問題 19

次の情報が与えられている。

1900年1月1日は月曜日である。
9月、4月、6月、11月は30日まであり、2月を除く他の月は31日まである。
2月は28日まであるが、うるう年のときは29日である。
うるう年は西暦が4で割り切れる年に起こる。しかし、西暦が400で割り切れず100で割り切れる年はうるう年でない。
20世紀(1901年1月1日から2000年12月31日)で月の初めが日曜日になるのは何回あるか。

------------------------------------------------------>*/

#include<iostream>
using namespace std;

const int yearBegin = 1901;
const int yearEnd   = 2001;

const int month[12]={ 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 };

//--------------------------------------->
//曜日を返す関数
//--------------------------------------->
int weekday( int cntDay ){
return cntDay % 7;
}

//--------------------------------------->
//うるう年判定
//--------------------------------------->
int leapYear( int year ){

if( year % 400 != 0 && year % 100 == 0 ) return 0;
else if ( year % 4 == 0 )return 1;
else return 0;
}

//--------------------------------------->
//
//--------------------------------------->

//1900年1月1日を1とする。
//月曜日を1とする → 日曜日は0となる
int main(){

int year = 1900;
int day = 0;
int ans = 0;

while( year < yearEnd ){

for(int i = 0 ; i < 12 ; i++){

//各月を追加
day += month[ i ];

//うるう年判定
if( i == 1 )day += (int)leapYear( year );
//条件の抽出
if( year >=yearBegin ){
if( weekday( day + 1 ) == 0 ) ans++;
}//end if
}//Next i

year++;
}

cout << "\nAnswer is \t" << ans;
getchar();
return 0;
};