HDU 3240 Counting Binary Trees(组合数学-斯特林数,数论-整数快速幂,数论-求逆元)

Counting Binary Trees

Problem Description

There are 5 distinct binary trees of 3 nodes:

Let T(n) be the number of distinct non-empty binary trees of no more than n nodes, your task is to calculate T(n) mod m.

Input

The input contains at most 10 test cases. Each case contains two integers n and m (1 <= n <= 100,000, 1 <= m <= 109) on a single line. The input ends with n = m = 0.

Output

For each test case, print T(n) mod m.

Sample Input

3 100
4 10
0 0

Sample Output

8
2

Source

2009 “NIT Cup” National Invitational
Contest

Recommend

zhonglihua   |   We have carefully selected several similar problems for you:  3249 3241 3242 3243 3244

题目大意:

问你不超过n个节点的二叉树的方案数,结果要对m求余。

解题思路:

方案数可以划分左右两边划分子问题也就是 h(n)=h(0)*h(n-1)+h(1)*(h-2)+..................+h(n-1)*h(0),一看就是卡特兰数,

关于卡特兰数必须要nlg^n的左右效率的算法解决

百度一下,知道:

令h(0)=1,h(1)=1,

catalan数满足:

递推式[1] :h(n)= h(0)*h(n-1)+h(1)*h(n-2) + ... + h(n-1)h(0) (n>=2)

递推式[2]  :h(n)=h(n-1)*(4*n-2)/(n+1);

递推式[3] :h(n)=C(2n,n)/(n+1) (n=0,1,2,...)

递推式[4] :h(n)=c(2n,n)-c(2n,n+1)(n=0,1,2,...)

我们选择,递推式[2]  :h(n)=h(n-1)*(4*n-2)/(n+1);

但是这个递推要求余,乘法求余没关系,除法要求逆元,除数有逆元的充要条件是 gcd(a,mod)==1,也就是除数与要模的那个数互质。

那么,我们对于mod分解因子,对于分母中的因子

(1)互质的数,分母直接求逆元

(2)不互质的数,无法求逆元,只能用分子去消。

解题代码:

#include <iostream>
#include <cstdio>
#include <map>
#include <vector>
#include <cstring>
using namespace std;

typedef long long ll;
const int maxn=50;
int tol,prime[maxn],cnt[maxn],n,mod;

void getPrime(){
    tol=0;
    int x=mod;
    for(int i=2;i*i<=x;i++){
        if(x%i==0){
            prime[tol++]=i;
            while(x%i==0) x/=i;
        }
    }
    if(x>1) prime[tol++]=x;
}

void extend_gcd(int a,int b,int &x,int &y){
     if(b==0){
        x=1;
        y=0;
     }else{
        extend_gcd(b,a%b,x,y);
        int tmp=x;
        x=y;
        y=tmp-(a/b)*y;
     }
}

int inv(int a,int mod){
    int x,y;
    extend_gcd(a,mod,x,y);
    return (x%mod+mod)%mod;
}

void deal1(ll &ret,int x){
    for(int i=0;i<tol;i++){
        while(x%prime[i]==0){
            x/=prime[i];
            cnt[i]++;
        }
    }
    ret=(ret*x)%mod;
}

void deal2(ll &ret,int x){
    for(int i=0;i<tol;i++){
        while(x%prime[i]==0){
            x/=prime[i];
            cnt[i]--;
        }
    }
    if(x>1){
        int tmp=inv(x,mod);
        ret=(ret*tmp)%mod;
    }
}

ll pow_mod(ll a,ll b,ll p){
    ll sum=1;
    while(b>0){
        if(b&1) sum=(sum*a)%p;
        a=(a*a)%p;
        b/=2;
    }
    return sum%p;
}

void solve(){
    ll ans=1,ret=1;
    memset(cnt,0,sizeof(cnt));
    getPrime();
    for(int i=2;i<=n;i++){
        deal1(ret,4*i-2);
        deal2(ret,i+1);
        ll tmp=ret;
        for(int t=0;t<tol;t++){
            tmp=( tmp*pow_mod(prime[t],cnt[t],mod) )%mod;
        }
        ans=(ans+tmp)%mod;
    }
    cout<<ans<<endl;
}

int main(){
    while(cin>>n>>mod && (n||mod) ){
        solve();
    }
    return 0;
}
时间: 2024-11-03 05:25:14

HDU 3240 Counting Binary Trees(组合数学-斯特林数,数论-整数快速幂,数论-求逆元)的相关文章

POJ 2154 Color(组合数学-波利亚计数,数论-欧拉函数,数论-整数快速幂)

Color Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 7693   Accepted: 2522 Description Beads of N colors are connected together into a circular necklace of N beads (N<=1000000000). Your job is to calculate how many different kinds of th

HDU 4045 Machine scheduling (组合数学-斯特林数,组合数学-排列组合)

Machine scheduling Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1000    Accepted Submission(s): 363 Problem Description A Baidu's engineer needs to analyze and process large amount of data o

HDU - 1588 Gauss Fibonacci (矩阵快速幂+二分求等比数列和)

Description Without expecting, Angel replied quickly.She says: "I'v heard that you'r a very clever boy. So if you wanna me be your GF, you should solve the problem called GF~. " How good an opportunity that Gardon can not give up! The "Prob

hdu 5171 GTY&#39;s birthday gift(数学,矩阵快速幂)

题意: 开始时集合中有n个数. 现在要进行k次操作. 每次操作:从集合中挑最大的两个数a,b进行相加,得到的数添加进集合中. 以此反复k次. 问最后集合中所有数的和是多少. (2≤n≤100000,1≤k≤1000000000) 思路: 写出来发现是要求Fibonaci的前n个数的和. Fibonaci是用矩阵快速幂求的,这个也可以. [Sn,Fn,Fn-1]=[某个矩阵]*[Sn-1,Fn-1,Fn-2] [S2,F2,F1]=[2,1,1] 然后写,,, 这个代码有些繁琐,应该把矩阵操作单独

2014多校第一场 I 题 || HDU 4869 Turn the pokers(费马小定理+快速幂模)

题目链接 题意 : m张牌,可以翻n次,每次翻xi张牌,问最后能得到多少种形态. 思路 :0定义为反面,1定义为正面,(一开始都是反), 对于每次翻牌操作,我们定义两个边界lb,rb,代表每次中1最少时最少的个数,rb代表1最多时的个数.一张牌翻两次和两张牌翻一次 得到的奇偶性相同,所以结果中lb和最多的rb的奇偶性相同.如果找到了lb和rb,那么,介于这两个数之间且与这两个数奇偶性相同的数均可取到,然后在这个区间内求组合数相加(若lb=3,rb=7,则3,5,7这些情况都能取到,也就是说最后的

HDU 4549 M斐波那契数列(矩阵快速幂)

Problem Description M斐波那契数列F[n]是一种整数数列,它的定义如下: F[0] = a F[1] = b F[n] = F[n-1] * F[n-2] ( n > 1 ) 现在给出a, b, n,你能求出F[n]的值吗? Input 输入包含多组测试数据: 每组数据占一行,包含3个整数a, b, n( 0 <= a, b, n <= 10^9 ) Output 对每组测试数据请输出一个整数F[n],由于F[n]可能很大,你只需输出F[n]对1000000007取模

HDU 2276 Kiki &amp; Little Kiki 2 (位运算+矩阵快速幂)

HDU 2276 Kiki & Little Kiki 2 (位运算+矩阵快速幂) ACM 题目地址:HDU 2276 Kiki & Little Kiki 2 题意: 一排灯,开关状态已知,每过一秒:第i个灯会根据刚才左边的那个灯的开关情况变化,如果左边是开的,它就会变化,如果是关的,就保持原来状态.问m秒后的状态. 第1个的左边是最后一个. 分析: 转移不好想啊... 变化是这样的: 原来 左边 变化 1 1 0 1 0 1 0 1 1 0 0 0 然后想到 (~原来)^(左边)=变化

hdu 3307 Description has only two Sentences (欧拉函数+快速幂)

Description has only two SentencesTime Limit: 3000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 852 Accepted Submission(s): 259 Problem Descriptionan = X*an-1 + Y and Y mod (X-1) = 0.Your task is to calculate th

HDU 3461 Code Lock(并查集的应用+快速幂)

* 65536kb,只能开到1.76*10^7大小的数组.而题目的N取到了10^7,我开始做的时候没注意,用了按秩合并,uset+rank达到了2*10^7所以MLE,所以貌似不能用按秩合并. 其实路径压缩也可以不用.............  题目的大意: 一个密码锁上有编号为1到N的N个字母,每个字母可以取26个小写英文字母中的一个.再给你M个区间[L,M],表示该区间的字母可以一起同步"增加"(从'a'变为'b'为增1,'z'增1为'a').假如一组密码按照给定的区间进行有限