import std.algorithm, std.array, std.container, std.range, std.bitmanip; import std.numeric, std.math, std.bigint, std.random, core.bitop; import std.string, std.regex, std.conv, std.stdio, std.typecons; long exGcd(long a, long b, ref long x, ref long y) { auto g = a; x = 1; y = 0; if (b != 0) { g = exGcd(b, a % b, y, x); y -= a / b * x; } return g; } long invMod(long x, long m) { long a = 1, b = 0; exGcd(x, m, a, b); return a; } const long mod = 10 ^^ 9 + 7; struct problem { string op; long n, k; } void main() { auto t = readln.chomp.to!int; auto pi = iota(t) .map!(_ => readln.chomp.match(r"(.)\((\d+),(\d+)\)").captures) .map!(m => problem(m[1], m[2].to!long, m[3].to!long)).array; auto maxN = pi.map!(p => p.op == "H" ? p.n + p.k : p.n).reduce!(max); auto facMemo = new long[](maxN + 1); facMemo[0] = 1; foreach (long i; 1..maxN + 1) facMemo[i] = (facMemo[i - 1] * i) % mod; auto invFacMemo = new long[](maxN + 1); invFacMemo[maxN] = invMod(facMemo[maxN], mod); foreach_reverse (long i; 0..maxN) invFacMemo[i] = (invFacMemo[i + 1] * (i + 1)) % mod; foreach (p; pi) { switch (p.op) { case "P": if (p.n < p.k) { writeln(0); } else { auto r = (facMemo[p.n] * invFacMemo[p.n - p.k]) % mod; writeln(r); } break; case "C": if (p.n < p.k) { writeln(0); } else { auto r = (facMemo[p.n] * invFacMemo[p.k]) % mod; r = (r * invFacMemo[p.n - p.k]) % mod; writeln(r); } break; case "H": if (p.n == 0 && p.k == 0) { writeln(1); } else { auto r = (facMemo[p.n + p.k - 1] * invFacMemo[p.k]) % mod; r = (r * invFacMemo[p.n - 1]) % mod; writeln(r); } break; default: assert(0); } } }