n wr= fracn! lfloorn/2 rfloor!2
binomn lfloorn/2 rfloor= fracn! lfloorn/2 rfloor! cdot lceiln/2 rceil!
n!= lfloorn/2 rfloor!2 cdotn wr
lp(n wr)= sumk geqslant1 lfloor fracnpk rfloormod2
\ begin {array} {ccl} l_p (n! / \ lfloor n / 2 \ rfloor! ^ 2) & = & l_p (n!) - 2l_p (\ lfloor n / 2 \ rfloor!) \\ & = & \ sum_ {k \ geqslant1} \ lfloor n / p ^ k \ rfloor-2 \ sum_ {k \ geqslant1} \ lfloor \ lfloor n / 2 \ rfloor / p ^ k \ rfloor \\ & = & \ sum_ {k \ geqslant1 } (\ lfloor n / p ^ k \ rfloor-2 \ lfloor \ lfloor n / p ^ k \ rfloor / 2 \ rfloor) \\\ end {array}
$$ display $$ \ begin {array} {lrrl} (a) & \ lfloor n / 2 \ rfloor & <p \ leqslant & n & \ Rightarrow & l_p (n \ wr) = 1 \\ (b) & \ lfloor n / 3 \ rfloor & <p \ leqslant & \ lfloor n / 2 \ rfloor & \ Rightarrow & l_p (n \ wr) = 0 \\ (c) & \ sqrt {n} & <p \ leqslant & \ lfloor n / 3 \ rfloor & \ Rightarrow & l_p (n \ wr) = \ lfloor n / p \ rfloor \: mod \: 2 \\ (d) & 2 & <p \ leqslant & \ sqrt {n} & \ Rightarrow & l_p (n \ wr) <log_2 (n) \\ (e) & & p = & 2 & \ Rightarrow & l_p (n \ wr) = \ sigma_2 (\ lfloor n / 2 \ rfloor) \\ \ end {array } $$ display $$
n wr= prodp leqslantnplp(n wr)
// main function public static BigInteger factorial(int n) { return factorial(n, primes(n)); } // recursive function with shared primes array private static BigInteger factorial(int n, int[] primes) { if (n < 2) return BigInteger.ONE; BigInteger f = factorial(n / 2, primes); BigInteger ps = primeSwing(n, primes); return f.multiply(f).multiply(ps); } // swinging factorial function private static BigInteger primeSwing(int n, int[] primes) { List<BigInteger> multipliers = new ArrayList<>(); for (int i = 0; i < primes.length && primes[i] <= n; i++) { int prime = primes[i]; BigInteger bigPrime = BigInteger.valueOf(prime); BigInteger p = BigInteger.ONE; int q = n; while (q != 0) { q = q / prime; if (q % 2 == 1) { p = p.multiply(bigPrime); } } if (!p.equals(BigInteger.ONE)) { multipliers.add(p); } } return product(multipliers, 0, multipliers.size() - 1); } // fast product for the list of numbers private static BigInteger product(List<BigInteger> multipliers, int i, int j) { if (i > j) return BigInteger.ONE; if (i == j) return multipliers.get(i); int k = (i + j) >>> 1; return product(multipliers, i, k).multiply(product(multipliers, k + 1, j)); } // Eratosthenes sieve private static int[] primes(int upTo) { upTo++; if (upTo >= 0 && upTo < 3) { return new int[]{}; } int length = upTo >>> 1; boolean sieve_bool[] = new boolean[length]; for (int i = 1, iterations = (int) Math.sqrt(length - 1); i < iterations; i++) { if (!sieve_bool[i]) { for (int step = 2 * i + 1, j = i * (step + 1); j < length; j += step) { sieve_bool[j] = true; } } } int not_primes = 0; for (boolean not_prime : sieve_bool) { if (not_prime) not_primes++; } int sieve_int[] = new int[length - not_primes]; sieve_int[0] = 2; for (int i = 1, j = 1; i < length; i++) { if (!sieve_bool[i]) { sieve_int[j++] = 2 * i + 1; } } return sieve_int; }
Source: https://habr.com/ru/post/323770/
All Articles