import java.io.BufferedReader import java.io.InputStream import java.io.InputStreamReader import java.io.PrintWriter import java.lang.StringBuilder import java.util.* const val inf:Long = 1000000000 var mod99:Long = 998244353 var mod10:Long = 1000000007 val reader = System.`in`.bufferedReader() val out = PrintWriter(System.out) fun main() { var comb = combination(2000001) var t = one_To_Int() for (i in 0 until t) { var x = input() if (x[0] == 'C') { var (n,m) = x.substring(2,x.length - 1).split(",").map{ it.toInt() } println(comb.C(n,m)) } if (x[0] == 'P') { var (n,m) = x.substring(2,x.length - 1).split(",").map{ it.toInt() } println(comb.P(n,m)) } if (x[0] == 'H') { var (n,m) = x.substring(2,x.length - 1).split(",").map{ it.toInt() } println(comb.H(n,m)) } } //out.flush() reader.close() } class combination(size:Int){ var fac = MutableList(size) {0} var inv = MutableList(size) {0} init { //階乗mod p var now_fac = 1L fac[0] = 1 inv[0] = 1 for (i in 1..size - 1){ now_fac *= i.toLong() now_fac %= mod10 fac[i] = now_fac } //逆元 for (i in 1..size - 1){ inv[i] = mod_pow(fac[i],mod10 - 2L,mod10) } } fun C(n:Int,m:Int):Long{ if (0 > m || m > n) return 0 return ((fac[n]*inv[m])%mod10)*inv[n - m]%mod10 } fun P(n:Int,m:Int):Long{ if (0 > m || m > n) return 0 return ((fac[n]*inv[n - m])%mod10) } fun H(n:Int,k:Int):Long{ if ((n == 0 && k > 0) || k < 0) return 0 return C(n + k - 1,k) } } fun init_String_SortedList():SortedSet{ return init_String_List().toSortedSet() } fun init_Int_SortedList():SortedSet{ return init_Int_List().toSortedSet() } fun init_Long_SortedList():SortedSet{ return init_Long_List().toSortedSet() } fun mod_pow(x:Long, n:Long, p: Long): Long { var ans = 1L var X: Long = x var N: Long = n while (N >= 1L) { if (N % 2 == 1L) { ans *= X ans = ans % p } X *= X X = X % p N = N / 2 } return ans } fun min(a:MutableList):Long{ var now :Long = 10000000000 for (i in 0..a.size - 1){ if (now > a[i]){ now = a[i] } } return now } fun max(a:MutableList):Long{ var now :Long = -100000000000 for (i in 0..a.size - 1){ if (now < a[i]){ now = a[i] } } return now } fun input():String{ return reader.readLine() } fun init_Long_List():MutableList{ var a = MutableList(0) { 0 } return a } fun init_String_List():MutableList{ var a = MutableList(0) { "" } return a } fun init_Int_List():MutableList{ var a = MutableList(0) { 0 } return a } fun list_To_Int():MutableList{ return input().split(" ").map{it.toInt()}.toMutableList() } fun list_To_Long():MutableList{ return input().split(" ").map{it.toLong()}.toMutableList() } fun one_To_Int():Int{ return input().toInt() } fun one_To_Long():Long { return input().toLong() } //fun deque():ArrayDeque{ // var queue:ArrayDeque = ArrayDeque() // return queue //} fun merge(A:MutableList,left:Int, mid:Int, right:Int) { var n1 = mid - left; var n2 = right - mid; var L = MutableList(n1 + 1) { 0 } var R = MutableList(n2 + 1) { 0 } for (i in 0..n1 - 1) { L[i] = A[left + i] } for (i in 0..n2 - 1){ R[i] = A[mid + i] } L[n1] = inf R[n2] = inf var i = 0 var j = 0 for (k in left..right - 1) { if (L[i] <= R[j]) { A[k] = L[i] i = i + 1 } else { A[k] = R[j] j = j + 1 } } } fun Sort(A:MutableList,left:Int, right:Int){ if (left+1 < right) { var mid = (left + right) / 2; Sort(A, left, mid) Sort(A, mid, right) merge(A, left, mid, right) } } fun gcd(a :Long ,b:Long):Long{ if (a % b == 0L){ return b }else{ return gcd(b,a%b) } }