title: 求组合数
date: 2022-11-14 23:08:43
tags: 组合数字
categories:
时间复杂度O(n2)O(n^2)O(n2)
使用递推公式:C(a,b)=(C(a−1,b−1)+C(a−1,b))modpC(a, b) = (C(a - 1, b - 1) + C(a - 1, b))\mod pC(a,b)=(C(a−1,b−1)+C(a−1,b))modp
final int maxn = (int) 2005;
long[][] c = new long[maxn][maxn];
Arrays.fill(c[0], 0);
c[0][0] = 1;
for (int i = 1; i < maxn; i++) {for (int j = 0; j < maxn; j++) {if (j != 0) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % p;else c[i][j] = 1;}
}
package ZuHe;/*** @author: Zekun Fu* @date: 2022/11/14 23:21* @Description: 使用费马小定理,求阶乘和阶乘的逆元*/
public class SecondZuHe {public static long qui(int a, int b, int mod) {long res = 1;while (b != 0) {if (b % 2 == 1) res = (res * a) % mod;a = (int)((long)a * a % mod);b >>= 1;}return res;}public static void getFac(long[] fac, long[] infac, int maxn, int mod) {
// System.out.println(qui(2, 3, mod));fac[0] = infac[0] = 1;for (int i = 1; i < maxn; i++) {fac[i] = fac[i - 1] * i % mod;infac[i] = qui(i, mod - 2, mod) * infac[i - 1] % mod;}}public static void main(String[] args) {System.out.println(qui(2, 3, 100));}
}
C(a,b)modp=C(amodp,bmodp)∗C(a/p,b/p)modbC(a, b) \mod p = C(a \mod p, b \mod p) * C(a / p, b / p) \mod bC(a,b)modp=C(amodp,bmodp)∗C(a/p,b/p)modb
package ZuHe;/*** @author: Zekun Fu* @date: 2022/11/14 23:55* @Description: 使用卢卡斯定理进行证明* C(a, b) = C(a % p, b % p) * C(a / p, b / p)** 1. 首先使用thirdZuhe进行初始化* 2. 最后使用lucss进行计算。*/
public class ThirdZuHe {public static long qui(long a, long b, long p) {long res = 1;while (b != 0) {if (b % 2 == 1) res = res * a % p;a = a * a % p;b >>= 1;}return res;}private static long myC(long a, long b, long p) {if (a < b) return 0;long res = 1;for (long i = a, j = 1; j <= b; i--, j++) {res = res * i % p;res = res * qui(j, p - 2, p) % p;}
// for (int i = 1; i <= b; i++) res = res / i;return (int)res % p;}private static long C(long a, long b, long p){long res = 1;for(long i = 1, j = a;i <= b;++i, --j){res = res * j % p;res = res * qui(i, p - 2, p) % p;}return res % p;}public static long mylucas(long a, long b, int p) {if (a < p && b < p) return C(a, b, p);return mylucas(a % p, b % p, p) * mylucas(a / p, b / p, p) % p;}public static long lucas(long a, long b, long p){if(a < p && b < p) return C(a, b, p);return C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;}public static void main(String[] args) {
// System.out.println(SecondZuHe.qui(1, 10, 10000));System.out.println(C(211, 95, 23));System.out.println(lucas(211, 95, 23));}}
质因数分解,要求i * primes[j] <= a,否则可能数组越界。
为什么求a!中包含质因数的个数的时候,不能出现那种情况呢?
大数乘法过程最后的t别忘了 t % 10, t /= 10
package ZuHe;import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;/*** @author: Zekun Fu* @date: 2022/11/15 17:52* @Description: 第四种组合,大数字的组合** 1. 首先求出阶乘的素数因子的幂* 2. 其次使用大数乘法进行运算,不用使用快速幂了,因为因子的总个数不会超过* 5000。** p1^sum1 * p2 ^ sum2 ... * pn ^ sumn*/
public class ForthZuHe {// a * bpublic static List get_primes(int a) {Listprimes = new ArrayList<>();boolean[] st = new boolean[a + 5];Arrays.fill(st, true);for (int i = 2; i <= a; i++) {if (st[i]) {primes.add(i);}for (int j = 0; primes.get(j) <= a / i;j++) {st[primes.get(j) * i] = false;if (i % primes.get(j) == 0) break;}}return primes;}public static List mul(Lista, int b) {int n = a.size();Listans = new ArrayList<>();int t = 0;for (int i = 0; i < n; i++) {t += a.get(i) * b;ans.add(t % 10);t /= 10;}while (t != 0) {ans.add(t % 10);t /= 10;}return ans;}// 计算a!中含有多少个素数pprivate static int get(int a, int p) {int s = 0;
// while (a >= p) { // 对于每一个数字有多少个个k就会被计算多少回
// s += a / p;
// p *= p;
// }while (a != 0) {s += a / p;a /= p;}return s;}public static void main(String[] args) {Scanner sc = new Scanner(System.in);int a = sc.nextInt();int b = sc.nextInt();Listprimes = get_primes(a);Listsum = new ArrayList<>();for (Integer p : primes) {sum.add(get(a, p) - get(b, p) - get(a - b, p));}Listans = new ArrayList<>();ans.add(1);
// BigInteger ans = new BigInteger("1");for (int i = 0; i < primes.size(); i++) {int x = primes.get(i);for (int j = 0; j < sum.get(i); j++) {
// ans = ans.multiply(new BigInteger(x + ""));ans = mul(ans, x);}}
// System.out.println(ans);for (int i = ans.size() - 1; i >= 0; i--) {System.out.print(ans.get(i));}System.out.println();}
}