例题1:求组合数 I
给定 n 组询问,每组询问给定两个整数 a,b,请你输出
的值。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一组 a 和 b。
输出格式
共 n 行,每行输出一个询问的解。
数据范围
1≤n≤10000,
1≤b≤a≤2000
输入样例:
3
3 1
5 3
2 2
输出样例:
3
10
1
答案:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
static final int N = 2010, mod = (int) (1e9 + 7);
static int[][] c = new int[N][N];
public static void init() {
for (int i = 0; i < N; i++)
for (int j = 0; j <= i; j++)
if (j == 0) c[i][j] = 1;
else c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % mod;
}
public static void main(String[] args) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String[] str = bufferedReader.readLine().split(" ");
int n = Integer.parseInt(str[0]);
init();
for (int i = 0; i < n; i++) {
str = bufferedReader.readLine().split(" ");
int a = Integer.parseInt(str[0]);
int b = Integer.parseInt(str[1]);
System.out.println(c[a][b]);
}
}
}
例题2:求组合数 II
给定 n 组询问,每组询问给定两个整数 a,b,请你输出
的值。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一组 a 和 b。
输出格式
共 n 行,每行输出一个询问的解。
数据范围
1≤n≤10000,
1≤b≤a≤
1
0
5
10^5
105
输入样例:
3
3 1
5 3
2 2
输出样例:
3
10
1
答案:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static int N = 100010, mod = 1000000007;
public static long[] fact, infact;
public static long qmi(long a, long b, long p) {
long res = 1;
while (b > 0) {
if ((b & 1) > 0) res = res * a % p;
b = b >> 1;
a = a * a % p;
}
return res;
}
public static void main(String[] args) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String[] str = bufferedReader.readLine().split(" ");
int n = Integer.parseInt(str[0]);
fact = new long[N];
infact = new long[N];
fact[0] = infact[0] = 1;
for (int i = 1; i < N; i++) {
fact[i] = fact[i - 1] * i % mod; //阶乘
infact[i] = infact[i - 1] * qmi(i, mod - 2, mod) % mod; //快速幂逆元
}
for (int i = 0; i < n; i++) {
str = bufferedReader.readLine().split(" ");
int a = Integer.parseInt(str[0]);
int b = Integer.parseInt(str[1]);
System.out.println(fact[a] * infact[b] % mod * infact[a - b] % mod);
}
}
}
例题3:求组合数 III
给定 n 组询问,每组询问给定三个整数 a,b,p,其中 p 是质数,请你输出
的值。
输入格式
第一行包含整数 n。
接下来 n 行,每行包含一组 a,b,p。
输出格式
共 n 行,每行输出一个询问的解。
数据范围
1≤n≤20,
1≤b≤a≤
1
0
18
10^{18}
1018,
1≤p≤
1
0
5
10^5
105,
输入样例:
3
5 3 7
3 1 5
6 4 13
输出样例:
3
3
2
答案:
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class Main {
public static long p;
public static long qmi(long a, long k) {
long res = 1;
while (k > 0) {
if ((k & 1) > 0) res = (res * a) % p;
k = k >> 1;
a = (a * a) % p;
}
return res;
}
public static long C(long a, long b) {
long res = 1;
for (long i = 1, j = a; i <= b; i++, j--) {
res = ((res * j) % p);
res = (res * qmi(i, p - 2)) % p;
}
return res;
}
public static long lucas(long a, long b) {
if (a < p && b < p) return C(a, b);
return C(a % p, b % p) * lucas(a / p, b / p) % p;
}
public static void main(String[] args) throws Exception {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String[] str = bufferedReader.readLine().split(" ");
int n = Integer.parseInt(str[0]);
//卢卡斯定理
for (int i = 0; i < n; i++) {
str = bufferedReader.readLine().split(" ");
long a = Long.parseLong(str[0]);
long b = Long.parseLong(str[1]);
p = Long.parseLong(str[2]);
System.out.println(lucas(a, b));
}
}
}