1.预处理:
(1)公式:C(n,m) = A(n,m)/!m = n!/(!(n-m)!m).
(2)时间复杂度:N log N.
(3)代码:
void init()
{
fact[0] = infact[0] = 1;
for (int i = 1; i < N; i ++ )
{
fact[i] = (LL)fact[i - 1] * i % mod;
infact[i] = (LL)infact[i - 1] * qmi(i, mod - 2, mod) % mod;
}
}
int qmi(int a, int k, int p)
{
int res = 1;
while (k)
{
if (k & 1) res = (LL)res * a % p;
a = (LL)a * a % p;
k >>= 1;
}
return res;
}
void print()
{
printf("%d\n", (LL)fact[a] * infact[b] % mod * infact[a - b] % mod);
}
2.递推:
(1)公式:C(n,m) = C(n-1,m) + C(n-1,m-1).
(2)时间复杂度:N^2.
(3)代码:
void work()
{
for(int i = 0;i < N; i ++ )
for(int j = 0; j <= i; j ++ )
if(!j) g[i][j] = 1;
else g[i][j] = (g[i-1][j] + g[i-1][j-1])%mod;
}
3.卢卡斯定理(Lucas):
(1)公式: C(n, m) ≡ C(n % p, m % p) * C(n / p, m / p) (mod p).
(2)时间复杂度:log (p,N) p log p.
(3)代码:
LL qmi(LL a, LL k, LL p)
{
int res = 1;
while (k)
{
if (k & 1) res = res * a % p;
a = a * a % p;
k >>= 1;
}
return res;
}
LL C(LL a,LL b,LL p)
{
if(b > a) return 0;
LL res = 1;
for(int i = 1, j = a; i <= b; i ++ ,j -- )
{
res = res * j % p;
res = res * qmi(i,p-2,p) % p;
}
return res;
}
LL lucas(LL a, LL b, LL 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;
}
4.分解质因数法:
(1)公式:C(n,m) = n(n-1)……(n-m+1) / m(m-1)……1 = n(n-1)……(n-m+1)!(n-m) / m(m-1)……1!(n-m) = n!/(!(n-m)!m) = (p1^α1)(p2^α2)……(pk^αk).
(2)原理:(分子分解每个p的次数cnt - 分母分解每个p的次数cnt)*pi.
(3)代码:
void get_prime(int a)
{
for(int i = 2; i <= a; i ++ )
{
if(!st[i]) prime[cnt++] = i;
for(int j = 0; prime[j] <= a / i; j ++ )
{
st[prime[j]*i] = 1;
if(i % prime[j] == 0) break;
}
}
}
int get(int a,int p)
{
int res = 0;
while(a)
{
res = res + a / p;
a = a / p;
}
return res;
}
vector<int> mux(vector<int>a,int b)
{
vector<int>c;
int t = 0;
for(int i = 0; i < a.size(); i ++ )
{
t+=a[i]*b;
c.push_back(t%10);
t = t / 10;
}
while(t)
{
c.push_back(t%10);
t = t / 10;
}
return c;
}
int main()
{
int a,b;
cin>>a>>b;
get_prime(a);
for(int i = 0; i < cnt; i ++ )
{
int p = prime[i];
sum[i] = get(a,p) - get(b,p) - get(a-b,p);
}
res.push_back(1);
for(int i = 0; i < cnt; i ++ )
for(int j = 1; j <= sum[i]; j ++ )
res = mux(res,prime[i]);
for(int i = res.size()-1; i >= 0; i -- )
cout<<res[i];
return 0;
}