3037 插板法+lucas

先说下lucas定理

1)Lucas定理:p为素数,则有:

(2)证明: n=(ak...a2,a1,a0)p = (ak...a2,a1)p*p + a0 =  [n/p]*p+a0 (注意 这里()p表示的是p进制数),m=[m/p]*p+b0其次,我们知道,对任意质数p有(1+x)^p=1+(x^p)(mod p) 。我们只要证明这个式子:C(n,m)=C([n/p],[m/p]) * C(a0,b0)(mod p),那么就可以用归纳法证明整个定理。对于模p而言,我们有下面的式子成立:

上式左右两边的x的某项x^m(m<=n)的系数对模p同余。其中左边的x^m的系数是 C(n,m)。 而由于a0和b0都小于p,因此右边的x^m 一定是由 x^([m/p]*p) 和 x^b0 (即i=[m/p] , j=b0 ) 相乘而得 因此有:C(n,m)=C([n/p],[m/p]) * C(a0,b0)  (mod p)。

简化之后就有lu(n,m,p)=c(n%p,m%p,p)*lu(n/p,m/p,p)%p;

通过这个定理我们可以把c(n,m)的数量级降低,然后在计算组合数的时候,如果c(n,m)的值还是很大,我们可以用唯一分解定理来递推。

在计算c(n,m,p)的过程中,记得合理使用同余定理,这里由于有除数还要用到逆元。

http://acm.hdu.edu.cn/showproblem.php?pid=3037

题意:对于m个豆子,我们要存放在n颗树里,问有多少中存放方式。

题解:由于没有规定一定要把豆子全都放在树里,也就是说可能存在剩余的豆子。我们假设剩余的豆子在第n+1颗树上,用x(n)表示第n颗树上的豆子数量。那么就有 x(1)+x(2)+....x(n)+x(n+1)=m。我们左右两边都加上n+1个1那么就有x(1)+1+x(2)+1+....x(n+1)+1=m+n+1;这个等式的求解我们可以理解为从长度为n+m+1的绳子中切出n+1段来,典型的插板法(插板法的简单介绍https://wenku.baidu.com/view/7300b5745acfa1c7aa00cc5f.html),那么问题很明确了 就是求c(n+m,n)模p。

(假设一线段的最小单位为1,我们相把长度为n的线段划分为m段,那么我们可供划分的位置有n-1,需要在这些位置中选m-1个位置做处理所以结果为c(n-1,m-1)---- 插板法)

ac代码:

#include <cstdio>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
typedef long long int ll;
ll n,m,p;
ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0)
    {
        x=1;
        y=0;
        return a;
    }
    ll temp=exgcd(b,a%b,y,x);
    y-=(a/b)*x;//
    return temp;
}
ll inv(ll b,ll p)// 求逆元
{
    ll x,y;
    ll temp=exgcd(b,p,x,y);
    if(x < 0) x+=(p/temp);
    return x;
}
ll c(ll n,ll m,ll p)
{
    ll a,b;
    a=b=1;
    if(m > n) return 0;
    while(m)
    {
        a=(a*n)%p;
        b=(b*m)%p;
        n--;
        m--;
    }
    return (ll)a*inv(b,p)%p;
}
ll lucas(ll n,ll m,ll p)
{
    if(m==0) return 1;
    return (ll)lucas(n/p,m/p,p)*(ll)c(n%p,m%p,p)%p;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m>>p;
        cout<<lucas(n+m,n,p)<<endl;
    }
    return 0;
}
时间: 2024-12-18 23:24:59

3037 插板法+lucas的相关文章

ZOJ 3557-How Many Sets II(Lucas定理+插板法求组合数)

题目地址:ZOJ 3557 题意:给一个集合,一共n个元素,从中选取m个元素,满足选出的元素中没有相邻的元素,一共有多少种选法(结果对p取模1 <= p <= 10^9) 思路:用插板法求出组合数.既然是从n个数中选择m个数,那么剩下的数为n-m,那么可以产生n-m+1个空,这道题就变成了把m个数插到这n-m+1个空中有多少种方法,即C(n-m+1,m)%p.然后就Lucas定理上去乱搞.因为这道题的p较大,所以不能预处理. #include <stdio.h> #include

[ACM] hdu 3037 Saving Beans (Lucas定理,组合数取模)

Saving Beans Problem Description Although winter is far away, squirrels have to work day and night to save beans. They need plenty of food to get through those long cold days. After some time the squirrel family thinks that they have to solve a probl

插板法(排列组合)

插板法的条件 (1)每个元素都是相同的 (2)分成的组,每组的元素不为空 就比如下面这个例子,分出来的组的元素是不为空的 将10个相同的球放到3个不同的篮子里面去,每个篮子至少一个,问有多少种放法 0-0-0-0-0-0-0-0-0-0     0代表球,-代表板子, 将9个板插入到10个球中, 我们只要从中选出2个板子, 自然而然就把球分成三堆了 即C(9,2) 将10个相同的球放到3个不同的篮子里面去,每个篮子可以为空,问有多少种方法 因为每个篮子可以为空,即每组的元素可以为空, 不符合第二

插板法

https://baijiahao.baidu.com/s?id=1583148539639670534&wfr=spider&for=pc(文章原出处) 三道题,诠释"插板法"精髓.(核心是可以将求n个数和为m的方案数转化为m+n个物体分成n堆,每堆至少一个的问题,从而使用插板法) [1].10个相同的糖果,分给3个孩子A.B.C,每个孩子至少一个,有多少种不同的分法? [2].10个相同的糖果,分给3个孩子A.B.C,有多少种不同的分法? [3].10个相同的糖果,

HDU 3037 Saving Beans (隔板法+Lucas定理)

<题目链接> 题目大意:用$n$颗树保存不超过$m$颗豆子($n,m\leq10^9$)(不一定所有的树都有豆子保存),问你总共有多少种情况.答案对p取模(p保证是个素数). 解题分析:可以转化成 将$n$个相同的球放入$m$个集合中,有的集合中的球数可能为0的等价问题.很明显这可以用隔板法解决,答案为$C(n+m-1,m-1)$则题目解的个数可以转换成求: $C(n+m-1,0)+C(n+m-1,1)+C(n+m-1,2)+……+C(n+m-1,m-1)$ 利用组合数公式 $C(n,k) =

插板法、捆绑法、插空法

分组用插板.相邻用捆绑.不邻用插空   分组问题 [例1] 共有10完全相同的球分到7个班里,每个班至少要分到一个球,问有几种不同分法?     C(9,6) [例2]有8个相同的球放到三个不同的盒子里,共有( )种不同方法. A.35 B.28 C.21 D.45      C(10,2) [例3]15个相同的球放入编号为1.2.3的盒子内,盒内球数不少于编号数,有几种不同的放法? 解析:编号1:至少1个,符合要求.编号2:至少2个:需预先添加1个球,则总数-1编号3:至少3个,需预先添加2个

【51nod 1251】 Fox序列的数量(以及带限制插板法讲解)

为什么网上没有篇详细的题解[雾 可能各位聚聚觉得这道题太简单了吧 /kk 题意 首先题目是求满足条件的序列个数,条件为:出现次数最多的数仅有一个 分析 感谢 刚睡醒的 JZ姐姐在咱写题解忽然陷入自闭的时候为咱知道迷津 QwQ 那么套路来说第一想到的其实就是容斥辣 然后懒得想去网上黈力[雾 在然后,发现网上要么没推导公式(虽说是直接列不用化简的)要么就是推导公式是错的... 于是坐下来冷静分析:首先,我们考虑最高的出现次数为 x 的情况下,有多少个序列是满足条件的 容斥一发发现式子长这个样子(用到

HDU 3037 Saving Beans (Lucas定理)

/*求在n棵树上摘不超过m颗豆子的方案,结果对p取模. 求C(n+m,m)%p. 因为n,m很大,这里可以直接套用Lucas定理的模板即可. Lucas(n,m,p)=C(n%p,m%p,p)*Lucas(n/p,m/p,p): ///这里可以采用对n分段递归求解, Lucas(x,0,p)=1: 将n,m分解变小之后问题又转换成了求C(a/b)%p. 而C(a,b) =a! / ( b! * (a-b)! ) mod p 其实就是求 ( a! / (a-b)!) * ( b! )^(p-2)

HDU 3037 Saving Beans(Lucas定理的直接应用)

解题思路: 直接求C(n+m , m) % p , 由于n , m ,p都非常大,所以要用Lucas定理来解决大组合数取模的问题. #include <string.h> #include <iostream> #include <algorithm> #include <vector> #include <queue> #include <set> #include <map> #include <string&g