洛谷P3301 [SDOI2013]方程

链接

  https://www.luogu.org/problem/show?pid=3301

组合数取模

  有必要在这里插入对组合数取模的介绍。
  欲求

Cmn mod p

  如果p是比较小的素数,直接lucas定理求

ll C(ll n, ll m, ll p)
{
    if(m>n)return 0;
    return fact[n]*inv(fact[n-m],p)%p*inv(fact[m],p)%p;
}
ll lucas(ll n, ll m, ll p)
{
    if(m==0)return 1;
    return lucas(n/p,m/p,p)*C(n%p,m%p,p)%p;
}

  如果p是合数但能够分解成单个素数的乘积,分别求模各个素数因子意义下的 Cmn 然后 CRT 合并即可。
  如果p是普通合数,但是 p=pq11pq22...pqkk ,且 pqii 比较小,这就是今天要重点讨论的问题。
  首先肯定是分别求出然后再 CRT 合并,那么问题转成如何求 Cmn mod pt
  考虑公式

Cmn=n!m!(nm)!

  在这里 pt 肯定是合数,直接求逆元的话不保证互质。但是我们知道任何一个数 x ,都能表示成
x=e×pk

  这就是解决这道题目的关键, e 的部分由于和p 互质,所以可以直接用 exgcd 求出其逆元。 p 的那一部分,如果能够分别算出分子分母中p 的指数,就能够相减然后快速幂就能算出其对答案的贡献。
  现在问题分成两部分,对于一个 n!=e×pk 分别怎么求 e k 。对于下面要做的这道题, O(n) 是不现实的,我们有更快的算法。
  
n! mod p=1×2×3×...×n (mod p)

  我们把 p 的倍数提出来,
(1×2×...×n)×pnp(1×2×...×np)
前面的那些因为在 mod p 意义下,所以 >p 的取模之后可以变成 <p

你可能感兴趣的:(#,中国剩余定理,#,排列组合)