给出n,k.求含有n个节点的不同二叉树数目%k
Input
MULTI TEST CASE!!
每行两个整数n,k(1<=n<=10^9,1<=k<=32768)
Output
一行二叉树的数目%k
Sample Input
3 100
Sample Output
5
//师哥模板
#include <stdio.h> #include <utility> #include <vector> #include <algorithm>
int Pow(int x, int b) { int ret = 1; for(int s = x; b; b >>= 1) { if(b & 1) ret *= s; s *= s; } return ret; } int PowMod(int x, int b, int p) { int ret = 1 % p; for(int s = x % p; b; b >>= 1) { if(b & 1) { ret *= s; ret %= p; } s *= s; s %= p; } return ret; }
std::pair<int, int> ExGcd(int a, int b) { if(a == 0) return std::make_pair(0, 1); std::pair<int, int> s = ExGcd(b % a, a); return std::make_pair(s.second - b / a * s.first, s.first); }
int Inv(int a, int m) // ax == 1 mod m { // assert gcd(a, m) == 1 std::pair<int, int> s = ExGcd(a, m); // s.first * a + s.second * m == 1 return s.first < 0 ? s.first + m : s.first; }
std::pair<int, int> FacMod(int n, int p, int k) { // assert p > 1, k > 0 int pk = Pow(p, k); int S[pk]; S[0] = 1 % pk; for(int i = 1; i < pk; ++i) { S[i] = S[i - 1]; if(i % p != 0) { S[i] *= i; S[i] %= pk; } } int ret = 1 % pk, et = 0, ep = 0; // S[pk - 1]^et, p^ep while(n) { et += n / pk; ret *= S[n % pk]; ret %= pk; ep += n / p; n /= p; } ret *= PowMod(S[pk - 1], et, pk); ret %= pk; return std::make_pair(ret, ep); }
int CRT(int x1, int m1, int x2, int m2) // Linear Congruence Equation { // assert gcd(m1, m2) == 1 // let x == x1 * k1 + x2 * k2 mod m1*m2 // k1 == 1 mod m1, k1 == 0 mod m2 // k2 == 0 mod m1, k2 == 1 mod m2 std::pair<int, int> s = ExGcd(m1, m2); // s.first * m1 + s.second * m2 == 1 int k1 = s.second * m2, k2 = s.first * m1; int t = (x1 * k1 + x2 * k2) % (m1 * m2); return t < 0 ? t + m1 * m2 : t; }
std::vector<std::pair<int, int> > Factorize(int n) { std::vector<std::pair<int, int> > ret; for(int x = 2; x * x <= n; ++x) { if(n % x == 0) { int c = 0; while(n % x == 0) { ++c; n /= x; } ret.push_back(std::make_pair(x, c) ); } } if(n > 1) ret.push_back(std::make_pair(n, 1) ); return ret; }
int Calc(int n, int p) { std::vector<std::pair<int, int> > factors = Factorize(p); int x = 0, m = 1; for(int i = 0; i < factors.size(); ++i) { // C(n, k) mod p[i]^k[i] std::pair<int, int> f2n = FacMod(n * 2, factors[i].first, factors[i].second); std::pair<int, int> fn = FacMod(n, factors[i].first, factors[i].second); std::pair<int, int> fn1 = FacMod(n + 1, factors[i].first, factors[i].second); int pk = Pow(factors[i].first, factors[i].second); int t = f2n.first * Inv(fn.first, pk) % pk; t = t * Inv(fn1.first, pk) % pk; t = t * PowMod(factors[i].first, f2n.second - fn.second - fn1.second, pk) % pk; x = CRT(x, m, t, pk); m *= pk; } return x; }
int main() { int n, p; while(scanf("%d%d", &n, &p) != -1) printf("%d/n", Calc(n, p) ); return 0; }
//其他模板
#include <cstdio> #include <cmath> #include <stdlib.h> #include <memory.h>
typedef int typec; typec GCD(typec a, typec b) { return b? GCD(b, a % b) : a; }
typec extendGCD(typec a, typec b, typec& x, typec& y) { if(!b) return x = 1, y = 0, a; typec res = extendGCD(b, a % b, x, y), tmp = x; x = y, y = tmp -(a/b)*y; return res; } typec power(typec x, typec k) { typec res = 1; while(k) { if(k&1) res *= x; x *= x, k >>= 1; } return res; } typec powerMod(typec x, typec k, typec m) { typec res = 1; while(x %= m, k) { if(k&1) res *= x, res %= m; x *= x, k >>= 1; } return res; } typec inverse(typec a, typec p, typec t = 1) { typec pt = power(p, t); typec x, y; y = extendGCD(a, pt, x, y); return x < 0? x += pt : x; } typec linearCongruence(typec a, typec b, typec p, typec q) { typec x, y; y = extendGCD(p, q, x, y); x *= b - a, x = p * x + a, x %= p * q; if(x < 0) x += p * q; return x; }
const int PRIMEMAX = 1000; int prime[PRIMEMAX + 1]; int getPrime() { memset(prime, 0, sizeof(int) * (PRIMEMAX + 1)); for(int i = 2; i <= PRIMEMAX; i++) { if(!prime[i]) prime[++prime[0]] = i; for(int j = 1; j <= prime[0] && prime[j] <= PRIMEMAX/i; j++) { prime[prime[j]*i] = 1; if(i % prime[j] == 0) break; } } return prime[0]; } int factor[100][3], facCnt; int getFactors(int x) { facCnt = 0; int tmp = x; for(int i = 1; prime[i] <= tmp / prime[i]; i++) { factor[facCnt][1] = 1, factor[facCnt][2] = 0; if(tmp % prime[i] == 0) factor[facCnt][0] = prime[i]; while(tmp % prime[i] == 0) factor[facCnt][2]++, factor[facCnt][1] *= prime[i], tmp /= prime[i]; if(factor[facCnt][2]) facCnt++; } if(tmp != 1) factor[facCnt][0] = tmp, factor[facCnt][1] = tmp, factor[facCnt++][2] = 1; return facCnt; }
typec combinationModPt(typec n, typec k, typec p, typec t = 1) { if(k > n) return 0; if(n - k < k) k = n - k; typec pt = power(p, t); typec a = 1, b = k + 1, x, y; int pcnt = 0; while(b % p == 0) pcnt--, b /= p; b %= pt; for(int i = 1; i <= k; i++) { x = n - i + 1, y = i; while(x % p == 0) pcnt++, x /= p; while(y % p == 0) pcnt--, y /= p; x %= pt, y %= pt, a *= x, b *= y; a %= pt, b %= pt; } if(pcnt >= t) return 0; extendGCD(b, pt, x, y); if(x < 0) x += pt; a *= x, a %= pt; return a * power(p, pcnt) % pt; }
const typec PTMAX = 32768; typec facmod[PTMAX]; void initFacMod(typec p, typec t = 1) { typec pt = power(p, t); facmod[0] = 1 % pt; for(int i = 1; i < pt; i++) { if(i % p) facmod[i] = facmod[i - 1] * i % pt; else facmod[i] = facmod[i - 1]; } } typec factorialMod(typec n, typec &pcnt, typec p, typec t = 1) { typec pt = power(p, t), res = 1; typec stepCnt = 0; while(n) { res *= facmod[n % pt], res %= pt; stepCnt += n /pt, n /= p, pcnt += n; } res *= powerMod(facmod[pt - 1], stepCnt, pt); return res %= pt; }
typec combinationModPtFac(typec n, typec k, typec p, typec t = 1) { if(k > n || p == 1) return 0; if(n - k < k) k = n - k; typec pt = power(p, t), pcnt = 0, pmcnt = 0; if(k < pt) return combinationModPt(n, k, p, t); initFacMod(p, t); typec a = factorialMod(n, pcnt, p, t); typec b = factorialMod(k, pmcnt, p, t); b *= b, pmcnt <<= 1, b %= pt; typec tmp = k + 1; while(tmp % p == 0) tmp /= p, pmcnt++; b *= tmp % pt, b %= pt; pcnt -= pmcnt; if(pcnt >= t) return 0; a *= inverse(b, p, t), a %= pt; return a * power(p, pcnt) % pt; } typec combinationModFac(typec n, typec k, typec m) { getFactors(m); typec a, b, p, q; for(int i = 0; i < facCnt; i++) { if(!i) a = combinationModPtFac(n, k, factor[i][0], factor[i][2]), p = factor[i][1]; else b = combinationModPtFac(n, k, factor[i][0], factor[i][2]), q = factor[i][1]; if(!i) continue; a = linearCongruence(a, b, p, q), p *= q; } return a; } int main() { getPrime(); typec n, k; while(scanf("%d %d", &n, &k) != EOF) printf("%d/n", combinationModFac(2 * n, n, k)); return 0; }