結果

問題 No.3677 Global Checksum
コンテスト
ユーザー harurun
提出日時 2026-09-03 16:07:56
言語 C++23(gcc16)
(gcc 16.1.0 + boost 1.92.0)
コンパイル:
g++-16 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
WA  
実行時間 -
コード長 5,040 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 908 ms
コンパイル使用メモリ 84,884 KB
実行使用メモリ 42,880 KB
最終ジャッジ日時 2026-09-04 23:12:11
合計ジャッジ時間 4,330 ms
ジャッジサーバーID
(参考情報)
judge6_0 / judge4_0
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample WA * 3
other WA * 20
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

/*
#include "testlib.h"

int main(int argc, char* argv[]){
    registerValidation(argc, argv);

    int H = inf.readInt(1,1'000'000);
    inf.readSpace();
    int W = inf.readInt(1, 4'000'000);
    ensuref((long long)H * (long long)W <= 4'000'000, "HxW violation");
    inf.readEoln();
    for(int i = 0; i < H; i++){
        for(int j = 0; j < W; j++){
            if(j > 0){
                inf.readSpace();
            }
            int A = inf.readInt(0, 1'000'000'000);
        }
        inf.readEoln();
    }
    inf.readEof();
}
*/


#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <vector>

#if defined(__GNUC__)
#define INLINE __attribute__((always_inline)) inline
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define INLINE inline
#define UNLIKELY(x) (x)
#endif

namespace Validator {

const char* p;
const char* endp;

[[noreturn]]
void fail() {
    _exit(1);
}

INLINE bool digit(char c) {
    return static_cast<unsigned>(c - '0') <= 9;
}

// H, W 専用。
// A と違って2回しか呼ばれないので普通に数値化する。
INLINE uint32_t readInt(uint32_t lo, uint32_t hi) {
    if (UNLIKELY(p == endp || !digit(*p))) {
        fail();
    }

    uint32_t x = 0;

    do {
        uint32_t d = *p - '0';

        if (UNLIKELY(x > (hi - d) / 10)) {
            fail();
        }

        x = x * 10 + d;
        ++p;
    } while (p != endp && digit(*p));

    if (UNLIKELY(x < lo)) {
        fail();
    }

    return x;
}

INLINE void readSpace() {
    if (UNLIKELY(p == endp || *p != ' ')) {
        fail();
    }
    ++p;
}

INLINE void readEoln() {
    if (UNLIKELY(p == endp)) {
        fail();
    }

    if (*p == '\n') {
        ++p;
        return;
    }

    if (*p == '\r') {
        if (UNLIKELY(p + 1 == endp || p[1] != '\n')) {
            fail();
        }

        p += 2;
        return;
    }

    fail();
}

// 0 <= A <= 1,000,000,000
//
// 数値への変換はしない。
// 先頭の 0 を除いた桁数だけでほぼ判定できる。
INLINE void readA() {
    if (UNLIKELY(p == endp)) {
        fail();
    }

    // testlib の readInt と同様に -0 は許容する。
    if (*p == '-') {
        ++p;

        if (UNLIKELY(p == endp || !digit(*p))) {
            fail();
        }

        do {
            if (UNLIKELY(*p != '0')) {
                fail();
            }
            ++p;
        } while (p != endp && digit(*p));

        return;
    }

    if (UNLIKELY(!digit(*p))) {
        fail();
    }

    const char* s = p;

    // 数字列を1回走査するだけ。
    do {
        ++p;
    } while (p != endp && digit(*p));

    // leading zero を無視。
    while (s != p && *s == '0') {
        ++s;
    }

    size_t n = static_cast<size_t>(p - s);

    // 10桁より大きければ > 1e9
    if (UNLIKELY(n > 10)) {
        fail();
    }

    // 先頭0を除いて10桁の場合、
    // <= 1e9 なのは 1000000000 のみ。
    if (UNLIKELY(
        n == 10 &&
        __builtin_memcmp(s, "1000000000", 10) != 0
    )) {
        fail();
    }
}

void validate() {
    int H = static_cast<int>(
        readInt(1, 1'000'000)
    );

    readSpace();

    int W = static_cast<int>(
        readInt(1, 4'000'000)
    );

    if (UNLIKELY(
        static_cast<int64_t>(H) * W > 4'000'000
    )) {
        fail();
    }

    readEoln();

    for (int i = 0; i < H; ++i) {
        for (int j = 0; j < W; ++j) {
            readA();

            if (j + 1 != W) {
                if (UNLIKELY(p == endp || *p != ' ')) {
                    fail();
                }
                ++p;
            }
        }

        readEoln();
    }

    if (UNLIKELY(p != endp)) {
        fail();
    }
}

} // namespace Validator

int main() {
    using namespace Validator;

    // stdin が通常ファイルならコピーせず mmap する。
    struct stat st{};

    if (
        fstat(STDIN_FILENO, &st) == 0 &&
        S_ISREG(st.st_mode)
    ) {
        size_t n = static_cast<size_t>(st.st_size);

        if (n == 0) {
            return 1;
        }

        void* data = mmap(
            nullptr,
            n,
            PROT_READ,
            MAP_PRIVATE,
            STDIN_FILENO,
            0
        );

        if (data != MAP_FAILED) {
            p = static_cast<const char*>(data);
            endp = p + n;

            validate();
            return 0;
        }
    }

    // pipe 等で mmap できない場合のみ fallback。
    std::vector<char> buf;

    constexpr size_t CHUNK = 1 << 20;
    char tmp[CHUNK];

    for (;;) {
        ssize_t r = read(
            STDIN_FILENO,
            tmp,
            sizeof(tmp)
        );

        if (r < 0) {
            return 1;
        }

        if (r == 0) {
            break;
        }

        buf.insert(
            buf.end(),
            tmp,
            tmp + r
        );
    }

    if (buf.empty()) {
        return 1;
    }

    p = buf.data();
    endp = p + buf.size();

    validate();
}
0