Submission #290101

#TimeUsernameProblemLanguageResultExecution timeMemory
290101model_codeChess Rush (CEOI20_chessrush)C++17
100 / 100
1034 ms8312 KiB
#include <iostream>
#include <algorithm>
#include <vector>

#include "arithmetics.h"

using namespace std;

int Q, R,C, start, finish;
char piece;

const int maxc=1010;
int fact[maxc];

void precalc() {
    fact[0] = 1;
    for (int i=1; i<maxc; ++i) {
        fact[i] = Mul(fact[i-1], i);
    }
}
int comb(int n, int k) {
    int ret = 1;
    for (int x=n-k+1; x<=n; ++x) {
        ret = Mul(ret, x);
    }
    return Div(ret, fact[k]);
}

pair<int,int> bounce_bishop(int s, int f, int r, int c) {
    pair<int,int> ret = { 0,0 };
    if (s!=1) {
        int wallrow = s;
        ret.first = 1+(r-wallrow)/(c-1);
        ret.second = 1;
        int remrow = (r-wallrow)%(c-1);
        bool fromleft=ret.first & 1;
        int impactfield = fromleft ? 1+remrow : c-remrow;
        if (remrow>0) ++ret.first;
        if (impactfield == f) return ret;
        if (remrow==0) ++ret.first;
        int freediag;
        if (fromleft) {
            if (f<impactfield) {
                freediag = c+1-(impactfield+f)/2-1;
                ++ret.first;
            }
            else {
                freediag = (f-impactfield)/2;
            }
        }
        else {
            if (f>impactfield) {
                freediag = (f+impactfield)/2-1;
                ++ret.first;
            }
            else {
                freediag = (impactfield-f)/2;
            }
        }
        ret.second = comb(ret.first-2+freediag,freediag);
    }
    return ret;
}

int DPup[maxc][maxc], newDP[maxc][maxc];
void onestep() {
    for (int s=0; s<C; ++s) for (int c=0; c<C; ++c) newDP[s][c]=0;
    for (int s=0; s<C; ++s) for (int c=0; c<C; ++c) {
        if (c>0) newDP[s][c-1] = Add(newDP[s][c-1], DPup[s][c]);
        newDP[s][c] = Add(newDP[s][c], DPup[s][c]);
        if (c+1<C) newDP[s][c+1] = Add(newDP[s][c+1], DPup[s][c]);
    }
    for (int s=0; s<C; ++s) for (int c=0; c<C; ++c) DPup[s][c] = newDP[s][c];
}
void doublestep() {
    for (int s=0; s<C; ++s) for (int c=0; c<C; ++c) newDP[s][c]=0;
    for (int s=0; s<C; ++s) {
        for (int mid=0; mid<C; ++mid) {
            newDP[s][0] = Add(newDP[s][0], Mul(DPup[s][mid],DPup[mid][0]));
        }
    }
    for (int e=1; e<C; ++e) newDP[0][e] = newDP[e][0], newDP[C-1][e] = newDP[C-1-e][0];
    for (int e=1; 2*e<C; ++e) {
        for (int s=1; s+1<C; ++s) {
            if (s-e>=0) newDP[s][e] = Add(newDP[s-e][0], newDP[s+1][e-1]);
            else newDP[s][e] = Add(newDP[s+e][0], newDP[s-1][e-1]);
        }
    }
    for (int e=(C-1)/2+1; e<C; ++e) {
        for (int s=1; s+1<C; ++s) {
            newDP[s][e] = newDP[C-1-s][C-1-e];
        }
    }
    for (int s=0; s<C; ++s) for (int c=0; c<C; ++c) DPup[s][c] = newDP[s][c];
}
void kingDP() {
    for (int s=0; s<C; ++s) for (int c=0; c<C; ++c) DPup[s][c] = 0;
    for (int s=0; s<C; ++s) {
        DPup[s][s]=1;
    }
    vector<bool> steplist;
    int r=R-1;
    while (r>0) {
        steplist.push_back(r&1);
        r >>= 1;
    }
    while (!steplist.empty()) {
        if (steplist.back()) onestep();
        steplist.pop_back();
        if (steplist.size()>0) doublestep();
    }
}

pair<int,int> pawnsolve() {
    if (start==finish) return {R-1,1};
    return {0,0};
}
pair<int,int> rooksolve() {
    if (start==finish) return {1,1};
    return {2,2};
}
pair<int,int> queensolve() {
    if (start==finish || finish-start == R-1) return {1,1};
    pair<int,int> ret = {2,2};
    if (start>finish-R+1) ret.second+=2;
    if (start-R+1>0) ret.second++;
    if (finish-R+1>0) ret.second++;
    if (finish+R-1<=C) ret.second++;
    if (start+R-1<=C) ret.second++;
    if ((start+1)%2 == (R+finish)%2) {
        int k = (R+finish-start-1)/2;
        int l = R-k-1;
        if (k>0 && l>0 && start-l>0) ret.second++;
        if (k>0 && l>0 && start+k<=C) ret.second++;
    }
    return ret;
}
pair<int,int> bishopsolve() {
    if ((start+1)%2 != (R+finish)%2) return {0,0};
    if (start+R-1 == finish || start-R+1==finish) return {1,1};
    int r=R,c=C;
    if (finish-start+1 > R) r=finish-start+1, c=R, start=1, finish=R;
    int k = (r+finish-start-1)/2;
    int l = r-k-1;
    int cnt = (start-l>0) + (start+k<=c);
    if (k>0 && l>0 && cnt>0) return {2,cnt};
    auto leftans = bounce_bishop(start,finish,r,c);
    auto rightans = bounce_bishop(c+1-start,c+1-finish,r,c);
    if (leftans.first==0 || (rightans.first>0 && leftans.first>rightans.first)) return rightans;
    if (rightans.first==0 || rightans.first>leftans.first) return leftans;
    return {leftans.first, Add(leftans.second,rightans.second)};
}
pair<int,int> kingsolve() {
    return {R-1, DPup[start-1][finish-1]};
}

void solve() {
    cin >> piece >> start >> finish;
    if (finish<start) start=C+1-start, finish=C+1-finish;
    pair<int,int> ans;
    if (piece=='P') ans = pawnsolve();
    if (piece=='R') ans = rooksolve();
    if (piece=='Q') ans = queensolve();
    if (piece=='B') ans = bishopsolve();
    if (piece=='K') ans = kingsolve();
    cout << ans.first << " " << ans.second << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin >> R >> C >> Q;
    precalc();
    kingDP();
    while (Q--) solve();
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...