HOJ 3240 Counting Binary Trees(卡特兰数,扩欧求逆元,经典)

卡特兰数,扩欧求逆元
题目意思:
n个节点的二叉树,可以构成有 catalan[n] 种不同的二叉树。 sum[n] 是卡特兰数前 n项的总和。
每次给出两个数 n, m, 求 sum[n] % m 是多少。
本题要点:
1、n很大,如果用大数来存第 100000 个卡特兰数,肯定超时。
2、卡特兰数的 递推公式
h[i] = h[i - 1] * (4 * i - 2) / (i + 1)
要求每一个卡特兰数 对m的模, 这里有除法,需要 求 (i + 1) 在模 m的情况下的逆元。
3、扩展欧几里得算法,求逆元
同余式 ax = 1(mod m), 如果 a, m 互质, 那么必然存在x, 使得 ax = 1(mod m)成立。
x 就是 a 在模 m下的逆元。 式子 ax = 1(mod m), 变形 ax - m*y = 1, 右扩展欧几里得算法,
直接求出x。
4、 本题中, (4 * i - 2) 与 m 不一定互质, (i + 1) 与 m 不一定互质,通过 m 进行因数分解来解决:
m 进行因数分解:
vector vc; // 存放 m 的各个素因子
5、 观察 式子 h[i] = h[i - 1] * (4 * i - 2) / (i + 1), 第一个卡特兰数 h[1] = 1
然后全部展开的话, h[i] = 1 * (6 / 3) * (10 / 4) * (14 / 5) * … * ( (4 * i - 2) / (i + 1) )
分子部分 (4 * i - 2) 所有的乘积,必然能够整除 所有 分母部分 (i + 1) 的所有乘积。
然后对于分子 temp = (4 * i - 2) ,如果能整除m的某个素因子 vc[j], temp /= vc[j], 同时 cnt[j]++;
假设除剩下来的 是 fz , 那么 fz 与 m 互质。
然后对于分母 temp = (i + 1) ,如果能整除m的某个素因子 vc[j], temp /= vc[j], 同时 cnt[j]–;
假设除剩下来的 是 fm , 那么 fm 与 m 互质。 可以用扩展欧几里得算法, 求 fm 在模m下的逆元了。
对于每一个 cnt[j], 不会有负数的。具体实现看代码,比较明了。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int MaxN = 100010;
typedef long long LL;
LL n, m;
int cnt[MaxN];	//存放相应的次数
vector<LL> vc;	// 存放 m 的各个素因子

LL exgcd(LL a, LL b, LL&x, LL& y)
{
   
	if(!b)
	{
   
		x = 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值