【数学】模运算类
/* 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);
}
}