-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmod.cpp
More file actions
122 lines (109 loc) · 3.53 KB
/
mod.cpp
File metadata and controls
122 lines (109 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#include <vector>
using namespace std;
#define PZ(x) PI((x).i);
template<class Short, class Long>
struct ZZ {
static Short MOD;
Short i;
ZZ():i(0) {}
ZZ(Short _i): i(_i >= 0 ? _i : _i + MOD) {}
ZZ(Long _i): i(_i % MOD >= 0 ? _i % MOD : _i % MOD + MOD) {}
Short val() { return i; }
static ZZ raw(Short _i) { return ZZ(_i); }
void operator +=(const ZZ& z) { i += z.i; if(i >= MOD) i -= MOD; }
void operator -=(const ZZ& z) { i -= z.i; if(i < 0) i += MOD; }
void operator *=(const ZZ& z) { i = (Long) i * z.i % MOD; }
void operator /=(const ZZ& z) { (*this) *= z.inverse(); }
ZZ operator +(const ZZ& z) const { ZZ ret(i); ret += z; return ret; }
ZZ operator -(const ZZ& z) const { ZZ ret(i); ret -= z; return ret; }
ZZ operator *(const ZZ& z) const { ZZ ret(i); ret *= z; return ret; }
ZZ operator /(const ZZ& z) const { return (*this) * z.inverse(); }
// ZZ operator -() const { return ZZ(-i); }
ZZ inverse() const {
return pow(MOD - 2);
}
ZZ pow(long long b) const {
ZZ x=Short(1),y=*this;
while(b > 0){
if(b%2 == 1)
x *= y;
y *= y; // squaring the base
b /= 2;
}
return x;
}
static vector<ZZ> factorial, inv_factorial;
static ZZ fact(int n) {
while(factorial.size() <= n)
factorial.push_back(factorial.back() * (int)factorial.size());
return factorial.at(n);
}
static ZZ inv_fact(int n) {
if (n < inv_factorial.size())
return inv_factorial.at(n);
int old_size = inv_factorial.size();
inv_factorial.resize(n+1);
inv_factorial.at(n) = fact(n).inverse();
for (int i = n-1; i >= old_size; i--) {
inv_factorial[i] = inv_factorial.at(i+1) * (i+1);
}
return inv_factorial.at(n);
}
static ZZ choose0(int n, int k) {
assert(n < 1e7);
if(n < k) return 0;
return fact(n) * (inv_fact(k) * inv_fact(n-k));
}
static ZZ choose1(int n, int k) {
assert(k < 1e7);
if (n < k) return 0;
if (k == 0) return 1;
return choose1(n-1, k-1) * n / k;
}
static pair<ZZ,int> factModExp(int n) {
if (n == 0) return {1, 0};
int e = n / MOD;
pair<ZZ,int> pr = factModExp(e);
if (e % 2) {
return MP(ZZ(0) - pr.first * fact(n % MOD), pr.second + e);
} else {
return MP(pr.first * fact(n % MOD), pr.second + e);
}
}
static ZZ choose2(int n, int k) {
assert(MOD < 1e7);
pair<ZZ,int> p1 = factModExp(n), p2 = factModExp(k), p3 = factModExp(n-k);
if (p1.second > p2.second + p3.second) return 0;
assert(p1.second == p2.second + p3.second);
return p1.first / (p2.first * p3.first);
}
};
typedef ZZ<int, long long> Z;
template<> int Z::MOD = 1000000007;
template<> vector<Z> Z::factorial(1, 1);
template<> vector<Z> Z::inv_factorial(1, 1);
long long mul(long long a,long long b,long long mod=Z::MOD){
long long x = 0,y=a%mod;
while(b > 0){
if(b%2 == 1){
x = x+y;
if(x >= mod) x -= mod;
}
y = y*2;
if(y >= mod) y -= mod;
b /= 2;
}
return x%mod;
}
long long pow(long long a, long long b, long long c=Z::MOD){
long long x=1,y=a; // ll is taken to avoid overflow of intermediate results
while(b > 0){
if(b%2 == 1){
x=mul(x, y, c);
}
y = mul(y, y, c); // squaring the base
b /= 2;
}
return x%c;
}
void _W(Z x) { printf("%d", x.i); }