浅谈逆元 (高中OJ3805)

44 篇文章 0 订阅
1 篇文章 0 订阅

先看一道题目:

  1. 【NOIP2014模拟8.24】小X 的二叉堆计数 (Standard IO)
    Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits
    Description
    众所周知,完全二叉树是一种二叉树,满足除最后一层外的每层结点都是满的,且最后一层的结点连续集中在左方。而二叉堆是一种完全二叉树,分为大根堆和小根堆,大根堆满足父结点的值不小于子结点的值,小根堆满足父结点的值不大于子结点的值。
    小X 最近对二叉堆和树的计数都很感兴趣,他想知道n 个互不相同的数能构成多少个不同的大小为n 的二叉堆,希望你帮帮他。
    Input
    第一行包含一个整数n。
    Output
    第一行包含一个整数,表示能构成的二叉堆个数模10^9 + 7。
    Sample Input
    3
    Sample Output
    4
    Data Constraint
    对于30% 的数据,n ≤ 10。
    对于60% 的数据,n ≤ 1000。
    对于80% 的数据,n ≤ 10^5。
    对于100% 的数据,1 ≤ n ≤ 5 × 10^6。

对于这道题目,先讲讲较为容易想到的方法。
设一个方程F[i]表示有I个节点时能构建的堆的个数。
方程:F[i]=F[i.left]*F[i.right]*C(i-1,i.left)
i.left和i.right分别表示在节点数为i的情况下完全二叉树的左右子树节点个数。
同时为了方便计算,可以先把要用到的节点处理一下,之后就只用计算这些节点。


BUT——
这个方法最大的问题就是求组合数。
看看组合数的公式:
N!
C(N,M)=————–
M!(N-M)!
因为算出来的数要MOD 10^9+7,所以我们只能把上下两个数分解,再互相抵消,最后边乘边mod。

设被除数和除数为a,b,这个公式应该是这样:
C(N,M)=a/b mod md (md=10^9+7)


思考:如何优化?
因为边乘边MOD,最后一起除会错,那为什么不可以把除法转成乘法?
得出:
a*(1/b) mod md
a我们很容易算,重点是算b。


再引入一个概念:
费马小定理:b^(c-1) mod c=1 (b为质数)
把式子左右两边同除b,得
b^(c-2) mod c=1/b


把得出来的式子代回去,得:(无视a)
b^(md-2) mod md
而10^9+7刚好又是一个质数,所以可以满足这个条件。


再把b拆开:
(M!(N-M)! mod md)^(md-2) mod md
现在就很好算了。


总结:

费马小定理:a^(c-1) mod c=1
得a^(c-2) mod c=1/c
把式子往回代,再用快速幂取模。
总之就是要仔细观察题目,多看几遍自然就明白了。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值