The 13th Zhejiang Provincial Collegiate Programming Contest D. The Lucky Week(zoj3939)

题意

告诉你某年某月某日是星期一,满足是1号,或者11号,或者21号,让你找出第n个这样的星期一(满足是1号,或者11号,或者21号)

思路

以为O(10000)可以过的,结果超时,为什么不一上来就写成O(1)的。。。。
400年一个循环,预处理好再做

代码:

#define rep(i, n) for (int i = 0; i < (n); i++)
#define FOR(i, n, m) for (int i = (n); i <= (m); i++)

typedef vector vi;

int gao(int year1, int month1, int day1, int year2, int month2, int day2)   {
    int nd, nm, ny; //new_day, new_month, new_year
    int od, om, oy; //old_day, oldmonth, old_year

    nm = (month2 + 9) % 12;
    ny = year2 - nm/10;
    nd = 365*ny + ny/4 - ny/100 + ny/400 + (nm*306 + 5)/10 + (day2 - 1);

    om = (month1 + 9) % 12;
    oy = year1 - om/10;
    od = 365*oy + oy/4 - oy/100 + oy/400 + (om*306 + 5)/10 + (day1 - 1);

    return od - nd;
}

const int N = 800 * 36 + 5;

int e, tol;
int Y[N], M[N], D[N], V[N], pos[N];
int c[N][7];
int dx[3] = {1, 11, 21};
vi g[7];

void init() {
    int x;
    e = 0, tol = 36 * 400;
    rep (i, 800) FOR (j, 1, 12) rep (k, 3) {
        Y[e] = i, M[e] = j, D[e] = dx[k];
        x = gao(i, j, dx[k], 0, 1, 1) % 7;
        V[e] = x;
        c[e][x]++;
        pos[e] = SZ(g[x]), g[x].pb(e);
        if (e != 0) rep (l, 7) c[e][l] += c[e - 1][l];
        e++;
    }
}

int T;
int y, m, d, n;

void solve() {
    int y1 = y % 400, m1 = m, d1 = d, cnt, mod, p;
    int id = 36 * y1 + 3 * (m1 - 1);
    rep (k, 3) {
        if (dx[k] == d1) break;
        id++;
    }
    cnt = c[id + tol][V[id]] - c[id][V[id]];
    p = n / cnt, cnt = n % cnt;
    id = g[V[id]][pos[id] + cnt];
    printf("%d %d %d\n", Y[id] - y1 + y + p * 400, M[id], D[id]);
}

int main() {
    init();
    scanf("%d", &T);
    while (T--) {
        scanf("%d %d %d %d", &y, &m, &d, &n);
        n--;
        solve();
    }
    return 0;
}

你可能感兴趣的:(The 13th Zhejiang Provincial Collegiate Programming Contest D. The Lucky Week(zoj3939))