// tested by Hightail - https://github.com/dj3500/hightail import std.stdio, std.string, std.conv, std.algorithm; import std.range, std.array, std.math, std.typecons, std.container, core.bitop; int t; void main() { scan(t); auto c = ModCombo(2 * 10^^6); while (t--) { auto s = readln.chomp; auto nk = s[2 .. $ - 1].split(',').to!(int[]); int n = nk[0], k = nk[1]; long ans; if (s[0] == 'P') { ans = c.perm(n, k); } else if (s[0] == 'C') { ans = c.binom(n, k); } else { if (n == 0 && k == 0) ans = 1L; else ans = c.binom(n + k - 1, k); } writeln(ans); } } struct ModCombo { private { immutable long _mod; long[] _f; long[] _finv; long _powmod(long x, long y, long mod) { return y > 0 ? _powmod(x, y>>1, mod)^^2 % mod * x^^(y&1) % mod : 1L; } } @property { long mod() {return _mod;} long f(int n) {return _f[n];} long finv(int n) {return _finv[n];} } this (int N, long mod = 10^^9 + 7) { _mod = mod; _f = new long[](N + 1); _finv = new long[](N + 1); _f[0] = _finv[0] = 1L; foreach (i ; 1 .. N + 1) { _f[i] = i * _f[i - 1] % _mod; } _finv[N] = _powmod(_f[N], _mod - 2, _mod); foreach_reverse (i ; 1 .. N) { _finv[i] = (i + 1) * _finv[i + 1] % _mod; } } long perm(int n, int k) { if (n < k) return 0L; return _f[n] * _finv[n - k] % _mod; } long binom(int n, int k) { if (n < k) return 0L; return _f[n] * _finv[k] % _mod * _finv[n - k] % _mod; } } void scan(T...)(ref T args) { string[] line = readln.split; foreach (ref arg; args) { arg = line.front.to!(typeof(arg)); line.popFront(); } assert(line.empty); } void fillAll(R, T)(ref R arr, T value) { static if (is(typeof(arr[] = value))) { arr[] = value; } else { foreach (ref e; arr) { fillAll(e, value); } } }