【数学】模运算类

/* MOD must be a prime. if not, don't use inv() */
const int MOD = 1e9 + 7;

struct ModularIntegers {
#define mint ModularIntegers
    int num;
    mint() {
        num = 0;
    }
    template <typename T>
    mint (const T& x) {
        ll tmp = x;
        if (tmp >= MOD) {
            if (tmp < (MOD << 1)) tmp -= MOD;
            else tmp %= MOD;
        } else if (tmp < 0) {
            if (tmp >= -MOD) tmp += MOD;
            else if (tmp %= MOD) tmp += MOD;
        }
        num = tmp;
    }
    friend mint operator+ (const mint &x, const mint &y) {
        return x.num + y.num;
    }
    friend mint operator- (const mint &x, const mint &y) {
        return x.num - y.num;
    }
    friend mint operator* (const mint &x, const mint &y) {
        return x.num * y.num;
    }
    friend mint operator/ (const mint &x, const mint &y) {
        return x * y.inv();
    }
    friend bool operator== (const mint &x, const mint &y) {
        return x.num == y.num;
    }
    friend bool operator!= (const mint &x, const mint &y) {
        return x.num != y.num;
    }
    mint operator+() {
        return +this->num;
    }
    mint operator-() {
        return -this->num;
    }
    mint& operator+= (const mint &x) {
        if ( (this->num += x.num) >= MOD) this->num -= MOD;
        return *this;
    }
    mint& operator-= (const mint &x) {
        if ( (this->num -= x.num) < 0) this->num += MOD;
        return *this;
    }
    mint& operator*= (const mint &x) {
        this->num = 1LL * this->num * x.num % MOD;
        return *this;
    }
    mint& operator/= (const mint &x) {
        this->num = ( (*this) * x.inv()).num;
        return *this;
    }
    mint pow (ll x) const {
        mint res (1), cur (this->num);
        for (; x; cur *= cur, x >>= 1)
            if (x & 1) res *= cur;
        return res;
    }
    mint inv() const {
        return pow (MOD - 2);
    }
    operator int() {
        return num;
    }
    operator uint() {
        return num;
    }
    operator ll() {
        return num;
    }
    operator ull() {
        return num;
    }
#undef mint
};
typedef ModularIntegers mint;
void _RD (mint &x) {
    scanf ("%d", &x.num);
}
void _WT (const mint &x) {
    printf ("%d", x.num);
}

这个代码几乎是可以满足所有正常需求了,除了自增自减这种不明所以的操作。

这个模运算类只应该被装载在在线比赛中的主要代码中,而不应该被其他模板(例如组合数学、多项式等)引用,这个模板的意义在于减少主代码里的复杂性,对于封装好的模板引入此模板有可能反而拖慢其速度。

测试代码:

void ModularIntegersTest() {
    for(int i = 1; i <= 200000; ++i) {
        mint a = 0;
        ll A = 0;

        ll rng = 1LL * rand() * rand();
        a -= rng;
        A -= rng;
        assert(a == (A % MOD + MOD) % MOD);
        WT(a, (A % MOD + MOD) % MOD);

        rng = 1LL * rand() * rand();
        a += rng;
        A += rng;
        WT(a, (A % MOD + MOD) % MOD);
        assert(a == (A % MOD + MOD) % MOD);

        rng = 1LL * rand() * rand();
        a *= rng;
        A *= rng;
        WT(a, (A % MOD + MOD) % MOD);
        assert(a == (A % MOD + MOD) % MOD);

        a = -a;
        A = -A;
        WT(a, (A % MOD + MOD) % MOD);
        assert(a == (A % MOD + MOD) % MOD);
    }
}