問題概要
$2015$年-$N$年の間($2015$や$N$も含む)で
yukicoder no.1の出題日(記事中に記載有り)が2014年と同じ曜日になる回数を求めてください。
カレンダーは現実世界と同じものを用いる。
うるう年は通常の判定方法を用いる。
・4で割れる年はうるう年である。
・ただし、100で割れるときは、うるう年ではない。
・ただし、400で割れるときは、うるう年である。
西暦N年の時点でもグレゴリオ暦を用いるとする。
$N\leqq10^{10}$
解法
target day: 2014年7月23日(水)
なんでFOR(i,2015,2015+(N-2014)%400)はOKで
FOR(i,2014 + t*400 + 1, N)はだめなんや? -> mod400の値がずれるため
計算量:$O(1)$
ソース
#include <bits/stdc++.h> using namespace std; using LL = long long; #define FOR(i, s, e) for (LL(i) = (s); (i) < (e); (i)++) int main() { cin.tie(0); ios_base::sync_with_stdio(false); //400年分単位で計算し、のこりはシュミレーション LL N; cin >> N; LL t = (N - 2014) / 400; LL ans = 0; {// block LL K = 0; LL sum = 0; FOR(i, 2015, 2015 + 400) { if (i % 400 == 0)sum += 2; else if (i % 100 == 0)sum += 1; else if (i % 4 == 0)sum += 2; else sum += 1; if (sum % 7 == 0)K++; } ans += t * K; } LL s = 2014 + t * 400; {// sumilation LL K = 0; LL sum = 0; FOR(i, 2015, 2015 + (N - 2014) % 400) { if (i % 400 == 0)sum += 2; else if (i % 100 == 0)sum += 1; else if (i % 4 == 0)sum += 2; else sum += 1; if (sum % 7 == 0)K++; } ans += K; } cout << ans << endl; return 0; }