Lucas定理及其应用
2014-09-28 19:39
176 查看
Lucas定理这里有详细的证明。
其实就是针对n, m很大时,要求组合数C(n, m) % p, 一般来说如果p <= 10^5,那么就能很方便的将n,m转化为10^5以下这样就可以按照乘法逆元的方法求解。
定义:
C(n, m) = C(n%p, m%p)*C(n/p, m/p) (mod p)
一种比较好理解的证明方式是这样的, 上面资料中有提到,
由p为质数,(1+x)^p = 1+x^p (mod p) p为质数,然后就是下面这幅图的内容了。
将n, m分别表示成p进制,n = n/p*p+a0, m = m/p*p+b0;
View Code
n个盒子每个盒子fi朵鲜花,选出s朵花,共有多少种选法?
分析:
每个盒子用(1+x^1+x^2..........x^fi)表示,总表达式∏(1+x^1+x^2..........x^fi) (0 <= i < n) = ∏(1-x^(fi+1)(0 <= i < n) * 1/(1-x)^n, 答案就是x^s的系数。
同样分成两部分 ∏(1-x^(fi+1)(0 <= i < n)和 1/(1-x)^n,后一部分很好求, x^k系数就是 C(n+k-1, n-1),前一部分x^i通过二进制表示法求出, 二进制每个位为1则表示拿出-x^(fi+1)相乘。那么问题关键在于C(n+k-1, n-1),对于C(n, m) = C(n%p, m%p)*C(n/p, m/p) mod p 由于m很小C(n/p, m/p)为1,那么C(n%p, m%p)很容易求得。
其实就是针对n, m很大时,要求组合数C(n, m) % p, 一般来说如果p <= 10^5,那么就能很方便的将n,m转化为10^5以下这样就可以按照乘法逆元的方法求解。
定义:
C(n, m) = C(n%p, m%p)*C(n/p, m/p) (mod p)
一种比较好理解的证明方式是这样的, 上面资料中有提到,
由p为质数,(1+x)^p = 1+x^p (mod p) p为质数,然后就是下面这幅图的内容了。
将n, m分别表示成p进制,n = n/p*p+a0, m = m/p*p+b0;
#include <cstdio> #include <iostream> #define bug(x) printf("%d\n", (x)); #define in freopen("solve_in.txt", "r", stdin); using namespace std; typedef long long LL; const int maxn = 22; const int M = (int)1e9+7; LL inv[maxn], fac[maxn]; LL powmod(LL a, LL b, LL c) { LL res = 1; while(b) { if(b&1) res = res*a%c; a = a*a%c; b >>= 1; } return res; } void pre() { fac[0] = 1; for(int i = 1; i < maxn; i++) fac[i] = fac[i-1]*i%M; for(int i = 1; i < maxn; i++) inv[i] = powmod(fac[i], M-2, M); } LL nCr(LL n, LL m) { n %= M; m %= M; if(m == 0) return 1; if(n < m) return 0; LL res = 1; for(int i = 0; i < m; i++) res = res*(n-i)%M; res = res*inv[m]%M; return res; } LL f[maxn]; void solve(LL n, LL ss) { LL ans = 0; for(int s = 0; s < (1<<n); s++) { LL sum = 0; int tag = 1; for(int i = 0; i < n; i++) if(s&(1<<i)) { sum += f[i]; if(sum > ss) break; tag *= -1; } if(sum <= ss){ ans = (ans+nCr(n+ss-sum-1, n-1)*tag+M)%M; } } if(ans < 0) ans += M; printf("%I64d\n", ans); } int main() { pre(); LL n, s; scanf("%I64d%I64d", &n, &s); for(int i = 0; i < n; i++) scanf("%I64d", f+i), f[i]++; solve(n, s); return 0; }
View Code
n个盒子每个盒子fi朵鲜花,选出s朵花,共有多少种选法?
分析:
每个盒子用(1+x^1+x^2..........x^fi)表示,总表达式∏(1+x^1+x^2..........x^fi) (0 <= i < n) = ∏(1-x^(fi+1)(0 <= i < n) * 1/(1-x)^n, 答案就是x^s的系数。
同样分成两部分 ∏(1-x^(fi+1)(0 <= i < n)和 1/(1-x)^n,后一部分很好求, x^k系数就是 C(n+k-1, n-1),前一部分x^i通过二进制表示法求出, 二进制每个位为1则表示拿出-x^(fi+1)相乘。那么问题关键在于C(n+k-1, n-1),对于C(n, m) = C(n%p, m%p)*C(n/p, m/p) mod p 由于m很小C(n/p, m/p)为1,那么C(n%p, m%p)很容易求得。
相关文章推荐
- poj 3146 Interesting Yang Hui Triangle(lucas定理的应用)
- 贝叶斯推断及其互联网应用(一):定理简介
- 剩余定理及其应用(杭电1061)
- 贝叶斯推断及其互联网应用(一):定理简介
- HDU 4349 Xiao Ming's Hope (Lucas定理的应用)
- “中国剩余定理”简介、算理及其应用
- 数论基础定理及其应用(hdu 2685 I won't tell you this is about number theory, hdu 2582 f(n),hdu 1792 A New Chan)
- 扩展欧几里得算法及其应用,逆元简介,中国剩余定理简介
- FZU 2020 组合(Lucas定理的应用)
- 贝叶斯推断及其互联网应用(一):定理简介
- HDU 4349——Lucas定理的巧妙应用
- 贝叶斯推断及其互联网应用(一):定理简介
- Havel-Hakimi定理及其应用
- poset_Dilworth定理及其应用
- 复分析学习10——Liouville定理及其应用
- 贝叶斯推断及其互联网应用(一):定理简介
- 贝叶斯推断及其互联网应用(一):定理简介
- 张恭庆编《泛函分析讲义》第二章第2节 $Riesz$ 定理及其应用习题解答
- 扩展欧几里得、求乘法逆元及其应用、中国剩余定理(互质版和非互质版)、欧拉函数、快速判素数模板
- 【转载】贝叶斯推断及其互联网应用(一):定理简介