给出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;
}
该博客探讨了如何计算含有特定数量节点的不同二叉树的总数,并将其结果对一个大素数取模。输入包括节点数量n和模数k,输出为二叉树的数量对k取模后的值。
401

被折叠的 条评论
为什么被折叠?



