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
题意:给你两个数n,m 问由1-n 个节点构成的二叉树个数之和mod m 后答案是多少。。
思路:由n 个节点的二叉树个数 我们可以知道这是Catalan 数的应用问题
可以用公式 但是 需要取mod 还有除法 所以需要用到逆元,对于互质的数直接求逆元,不互质的数,对mod 分解质因子,用分子抵消。。
代码如下:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=100005;
int n,m,len;
vector<int>prime;
int cnt[maxn];
void get_prime(int m)
{
int k=m;
for(int i=2;i*i<=k;i++)
{
if(k%i==0)
{
prime.push_back(i);
while(k%i==0)k/=i;
}
}
if(k>1)prime.push_back(k);
}
void entend_gcd(int a,int b,int &x,int &y)
{
if(b==0)
{
x=1;
y=0;
}
else
{
entend_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;
entend_gcd(a,mod,x,y);
return (x%mod+mod)%mod;
}
void sev1(ll &ret,int x)
{
for(int i=0;i<len;i++)
{
while(x%prime[i]==0)
{
x/=prime[i];
cnt[i]++;
}
}
ret=(ret*x)%m;
}
int sev2(ll &ret,int x)
{
for(int i=0;i<len;i++)
{
while(x%prime[i]==0)
{
x/=prime[i];
cnt[i]--;
}
}
if(x>1)
{
ll tmp=inv(x,m);
ret=(ret*tmp)%m;
}
}
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;
}
int main()
{
while(cin>>n>>m&&(n||m))
{
prime.clear();
get_prime(m);
len=prime.size();
memset(cnt,0,sizeof(cnt));
ll ans=1,ret=1;
for(int i=2;i<=n;i++)
{
sev1(ret,4*i-2);
sev2(ret,i+1);
ll tmp=ret;
for(int j=0;j<len;j++)
{
tmp=(tmp*pow_mod(prime[j],cnt[j],m))%m;
}
ans=(ans+tmp)%m;
}
printf("%lld\n",ans);
}
return 0;
}