888. 求组合数 IV
输入 a,b,求 4. 高精度求组合数 - 图1 的值。
注意结果可能很大,需要使用高精度计算。
输入格式
共一行,包含两个整数 a 和 b。
输出格式
共一行,输出 4. 高精度求组合数 - 图2 的值。
数据范围
1≤b≤a≤5000
输入样例:

  1. 5 3

输出样例:

  1. 10

要素

  • 一组数据
  • 1≤b≤a≤5000
  • 没有取模要求

结果可能很大,用高精度乘法和高精度除法做运算

问题来了,能不能只用乘法?
是可以的,将a和b都用算术基本定理分解为质因数的乘积,消去公共质因子后剩余的就只有乘法了。

求 a! 的分解质因数的结果

a! = x0``p0`` * x1``p1`` * ... * xk``pk
对于其中一个质因子x如何求它的次数?
cnt(x) = a // x + a//x``2`` + a//x``3`` + ...

  1. //求num! 分解质因子x 的次数
  2. static int get(int num, int x) {
  3. int ans = 0;
  4. while (num > 0) {
  5. ans += num / x;
  6. num /= x;
  7. }
  8. return ans;
  9. }
  1. import java.util.*;
  2. public class Main {
  3. static final int N = 5010;
  4. static int idx;
  5. static int[] primers = new int[N];
  6. static boolean[] st = new boolean[N + 1];
  7. static int[] sum = new int[N + 1];
  8. static {
  9. //预处理下1-N的所有质数
  10. for (int i = 2; i <= N; i++) {
  11. if (!st[i]) primers[idx++] = i;
  12. for (int j = 0; primers[j] <= N / i; j++) {
  13. st[primers[j] * i] = true;
  14. if (i % primers[j] == 0) break;
  15. }
  16. }
  17. }
  18. public static void main(String[] args) {
  19. Scanner sc = new Scanner(System.in);
  20. int a = sc.nextInt(), b = sc.nextInt();
  21. for (int i = 0; i < idx; i++) {
  22. sum[i] += get(a, primers[i]) - get(b, primers[i]) - get(a - b, primers[i]);
  23. }
  24. // for (int i = 0; i < idx; i++) {
  25. // System.out.println(primers[i] + " " + sum[i]);
  26. // }
  27. List<Integer> res = new ArrayList<>();
  28. res.add(1);
  29. for (int i = 0; i < idx; i++) {
  30. for (int j = 0; j < sum[i]; j++) {
  31. res = mul(res, primers[i]);
  32. }
  33. }
  34. for (int i = res.size() - 1; i >= 0; i--) {
  35. System.out.print(res.get(i));
  36. }
  37. }
  38. //求num! 分解质因子p 的次数
  39. static int get(int num, int p) {
  40. int ans = 0;
  41. while (num > 0) {
  42. ans += num / p;
  43. num /= p;
  44. }
  45. return ans;
  46. }
  47. //高精度乘法
  48. static List<Integer> mul(List<Integer> a, int b) {
  49. List<Integer> res = new ArrayList<>();
  50. int t = 0;
  51. for (int i = 0; i < a.size(); i++) {
  52. t += a.get(i) * b;
  53. res.add(t % 10);
  54. t /= 10;
  55. }
  56. while (t > 0) {
  57. res.add(t % 10);
  58. t /= 10;
  59. }
  60. return res;
  61. }
  62. }