Cod sursa(job #2767047)

Utilizator niculaandreiNicula Andrei Bogdan niculaandrei Data 4 august 2021 17:21:27
Problema Interclasari Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.88 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin("xcmmdc.in");
ofstream fout("xcmmdc.out");

const int N_MAX = 1005;
const int LOG_MAX = 11;

int N, M, K, Q, L;
int Log[N_MAX];
int RMQ[LOG_MAX][N_MAX][N_MAX];
int Mars[N_MAX];
int Ans[N_MAX];

int Query(int x, int y, int l)
{
    int ret = RMQ[Log[l]][x][y];
    ret = __gcd(ret, RMQ[Log[l]][x + l - (1 << Log[l])][y]);
    ret = __gcd(ret, RMQ[Log[l]][x][y + l - (1 << Log[l])]);
    ret = __gcd(ret, RMQ[Log[l]][x + l - (1 << Log[l])][y + l - (1 << Log[l])]);
    return ret;
}

int main()
{
    fin >> N >> M >> K >> Q;
    for (int i = 1; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            fin >> RMQ[0][i][j];
        }
    }

    for (int i = 2; i <= N_MAX; i++) {
        Log[i] = Log[i / 2] + 1;
    }

    for (int l = 1; l <= LOG_MAX; l++) {
        for (int i = 1; i <= N - (1 << l) + 1; i++) {
            for (int j = 1; j <= M - (1 << l) + 1; j++) {
                int gcd = RMQ[l - 1][i][j];
                gcd = __gcd(gcd, RMQ[l - 1][i + (1 << (l - 1))][j]);
                gcd = __gcd(gcd, RMQ[l - 1][i][j + (1 << (l - 1))]);
                gcd = __gcd(gcd, RMQ[l - 1][i + (1 << (l - 1))][j + (1 << (l - 1))]);
                RMQ[l][i][j] = gcd;
            }
        }
    }

    for (int i = 1 ; i <= N; i++) {
        for (int j = 1; j <= M; j++) {
            if (RMQ[0][i][j] % K == 0) {
                int mn = 1, mx = 1;

                int le = 1, ri = min(N - i + 1, M - j + 1), mid, q;
                while (le <= ri) {
                    mid = (le + ri) / 2;
                    q = Query(i, j, mid);
                    if (q == K) {
                        mn = mid;
                        ri = mid - 1;
                    }
                    else if (q < K) {
                        ri = mid - 1;
                    }
                    else {
                        le = mid + 1;
                    }
                }

                le = 1, ri = min(N - i + 1, M - j + 1);
                while (le <= ri) {
                    mid = (le + ri) / 2;
                    q = Query(i, j, mid);
                    if (q == K) {
                        mx = mid;
                        le = mid + 1;
                    }
                    else if (q < K) {
                        ri = mid - 1;
                    }
                    else {
                        le = mid + 1;
                    }
                }

                if (Query(i, j, mn) != K || Query(i, j, mx) != K) {
                    continue;
                }
                Mars[mn] += 1;
                Mars[mx + 1] -= 1;
            }
        }
    }

    for (int i = 1; i <= N_MAX; i++) {
        Ans[i] = Ans[i - 1] + Mars[i];
    }

    while (Q--) {
        fin >> L;
        fout << Ans[L] << "\n";
    }
    return 0;
}