Lucas 大组合数

题目:HDU 3037

题意:有n个树,m个坚果,放到n个树里,可以不放完,有多少种方法。

分析:

得到组合数了。

大组合数什么费马小定理,Lucas定理都来了;

总的说,不能用二维地推了,用的却是组合数的定义。

一般来说大组合通常要取模。

那么不能边乘边模,边除边模,等式不会成立。

根据逆元,除以一个数取模 = 乘以这个数对mod的逆元。

那么式子就可以写成:

这里,我们可以预处理所有 i 对 mod 的逆元后,累乘,这样得到的就是阶乘的逆元。

然后就是求 i 对 mod 的逆元了,什么扩展欧几里得就来了。

当然,有费马小定理。

inv[i] = (mod-mod/i)*inv[mod%i]%mod;

整个求大组合数就是这样出来了。

void init() {

    fac[0] = 1;
    for(int i=1;i<maxn;i++)
        fac[i] = i*fac[i-1]%mod;

    inv[0] = inv[1] = 1;
    for(int i=2;i<maxn;i++)
        inv[i] = (ll)(mod-mod/i)*inv[mod%i]%mod;

    for(int i=2;i<maxn;i++)
        inv[i] = inv[i-1]*inv[i]%mod;

}

ll C(ll n,ll m) {

    if(n<m)
        return 0;
    return fac[n]*inv[m]%mod*inv[n-m]%mod;

}

但是这个题目n,m的范围惊人1000000000,作为阶乘,逆元,数组开不下。

Lucas来了:

看结果吧:

还是有组合数,用了费马定理:

fac[n]*Inv(fac[m])%P*Inv(fac[n-m])%P;

因为这里的对P的逆元 Inv已经不能用数组表示和地推了,Inv()函数,利用了费马定理,快速幂等等,原理很复杂了,哈哈~~~,我就不证明了。

void initFac(int n) {
    fac[0] = 1;
    for(int i=1;i<=n;i++)
        fac[i] = i*fac[i-1]%P;
}

ll Pow(ll a,int b) {
    ll re = 1;
    for(;b;b>>=1,a=a*a%P)
        if(b&1) re = re*a%P;
    return re;
}

ll Inv(ll a) {
    return Pow(a,P-2);
}

ll C(ll n,ll m) {
    if(n<m) return 0;
    return fac[n]*Inv(fac[m])%P*Inv(fac[n-m])%P;
}

ll Lucas(ll n,ll m) {
    if(n<m) return 0;
    ll re = 1;
    for(;m;n/=P,m/=P)
        re = re*C(n%P,m%P)%P;
    return re;
}
时间: 2024-11-01 09:58:08

Lucas 大组合数的相关文章

大组合数取模之lucas定理模板,1&lt;=n&lt;=m&lt;=1e9,1&lt;p&lt;=1e6,p必须为素数

typedef long long ll; /********************************** 大组合数取模之lucas定理模板,1<=n<=m<=1e9,1<p<=1e6,p必须为素数 输入:C(n,m)%p 调用lucas(n,m,p) 复杂度:min(m,p)*log(m) ***********************************/ //ax + by = gcd(a,b) //传入固定值a,b.放回 d=gcd(a,b), x , y

多校杭电5794 大组合数(lucas)+dp

Problem Description There is a n×m board, a chess want to go to the position (n,m) from the position (1,1).The chess is able to go to position (x2,y2) from the position (x1,y1), only and if only x1,y1,x2,y2 is satisfied that (x2−x1)2+(y2−y1)2=5, x2>x

FZU 2020-组合(Lucas定理+逆元解决大组合数求模)

题目地址:FZU 2020 题意:求C(n,m)%p的值(1 <= m <= n <= 10^9, m <= 10^4, m < p < 10^9, p是素数). 思路: 对于和并且p是素数,我们一般采用Lucas定理来解. 1).Lucas定理是用来求 C(n,m) mod p的值,p是素数.其描述为: 如果 那么得到 即 Lucas(n,m,p)=C(n%p,m%p)* Lucas(n/p,m/p,p) Lucas(n,0,p)=1; 2).对于大组合数求模C(N,

Lucas定理--大组合数取模 学习笔记

维基百科:https://en.wikipedia.org/wiki/Lucas%27_theorem?setlang=zh 参考:http://blog.csdn.net/pi9nc/article/details/9615359 http://hi.baidu.com/lq731371663/item/d7261b0b26e974faa010340f http://hi.baidu.com/j_mat/item/8e3a891c258c4fe9dceecaba 综合以上参考,我做的一下总结:

HDU 3037 Saving Beans 大组合数 lucas定理

直接lucas降到10w以内搞组合数 #include <cstdio> #include <cstring> typedef __int64 LL; LL f[110010]; LL pow(LL a, LL b, LL c) { LL ans = 1; while(b) { if(b&1) ans = (ans*a) % c; b >>= 1; a = (a*a) % c; } return ans; } LL cm(LL n, LL m, LL p) {

大组合数取余模板【Lucas定理】

求C(n, m) % mod 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <bits/stdc++.h> using namespace std; long long fact[200200]; long long inv[200200]; const int mod = 1e9 + 7; long 

大组合数取模

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1119 考虑从(1,1)->(n,m)必定会向下走n-1步,向右走m-1步,那么总的走法是C(n-1+m-1,m-1). 关于组合数取模:大神博客:http://blog.csdn.net/acdreamers/article/details/8037918 1 #include <iostream> 2 #include <string.h> 3 #

欧拉公式 大组合数 2017 ICPC 乌鲁木齐 D Fence Building

题目链接:https://nanti.jisuanke.com/t/40515 题意:给你一个n,让你在圆上找n个点,最多能把圆分成多少个区域. 欧拉公式:R+V-E=2,其中的R,V,E分别是区域数,点数,边数 想分成最多的区域,只需要满足不会有3根线交于一个点就好. 尝试统计总的结点个数A(n),与独立线段(包括圆弧上的n段小弧)的总个数B(n),然后利用欧拉公式就可以得到答案 Ans(n)=B(n)−A(n)+1 这里之所以是加1是因为圆外那个区域我们不算任意四个点,会形成一个交点,并贡献

nefu 628大组合数取模

题目连接:http://acm.nefu.edu.cn/JudgeOnline/problemshow.php?problem_id=628 关于ACM培训的通知 Garden visiting Problem : 628 Time Limit : 1000ms Memory Limit : 65536K description There is a very big garden at Raven's residence. We regard the garden as an n*m rect