题目链接: https://ac.nowcoder.com/acm/contest/317/H
这道题是卡特兰数的变形,关于卡特兰数: https://blog.csdn.net/lanyanzhiji123asd/article/details/86770584
最后我们推出这道题的公式
然后对p去模,这道题的难点也是组合数取模 关于组合数取模的其他方法 https://blog.csdn.net/cai_haiq/article/details/75954298
题解用了一个巧妙的方法
组合数展开会变成
n!=p1^a1*p2^a2*p3^a3……;
p1,p2,p3…… 都是质数
所以其实分子分母都是多个质数相乘
所以我们求出所有的质数,然后对于每个质数,求出他们的指数
这样我们就可以取模了
这里要注意,储存质数那个数组要开2e6
关于求指数 就是cal这个函数 a/temp 其实是求1-a有多少个数可以整除temp
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
ll n,k,p;
int prime[2000005];
vector<ll>mp;
void is_prime()
{
ll i,j;
mp.clear();
memset(prime,0,sizeof(prime));
prime[1] = 1;
for(i = 2;i<=2000000;i++)
{
if(!prime[i])
{//cout << i << endl;
mp.push_back(i);
for(j = i*i;j<=2000000;j+=i)
{
prime[j] = 1;
}
}
}
}
ll qpow(ll a,ll b, ll mod)
{
ll res = 1;
while(b)
{
if(b%2!=0)
{
res*=a;
res%=mod;
}
a*=a;
a%=mod;
b/=2;
}
return res;
}
ll cal(ll a, ll b)
{
ll zhi = 0,temp = b;
while(a>=temp)
{
zhi+=a/temp;
temp*=b;
}
return zhi;
}
ll C(ll n,ll m,ll mod)
{
int i;
ll ans = 1, num = 0;
for(i = 0; i < mp.size()&&mp[i]<=n;i++)
{//cout << "qqqqq "<<mp[i] << endl;
num = cal(n,mp[i])-cal(m,mp[i])-cal(n-m,mp[i]);
ans*=qpow(mp[i],num,mod)%mod;
ans%=mod;
}
return ans;
}
int main()
{
std::ios::sync_with_stdio(false);
is_prime();
while(cin >> n>> k >> p)
{
cout << ((C(2*n,n,p)-C(2*n,n+k,p))%p+p)%p<< endl;
}
return 0;
}