分析:一看就知道是卡特兰数
卡特兰数的公式:
令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)
例如:h(2)=h(0)*h(1)+h(1)*h(0)=1*1+1*1=2
h(3)=h(0)*h(2)+h(1)*h(1)+h(2)*h(0)=1*2+1*1+2*1=5
另类递推式[2] :
h(n)=h(n-1)*(4*n-2)/(n+1);
递推关系的解为:
h(n)=C(2n,n)/(n+1) (n=0,1,2,…)
递推关系的另类解为:
h(n)=c(2n,n)-c(2n,n-1)(n=0,1,2,…)
这道题目用到了第二个递推式,赛场上记不到也没问题 记住形状
h[n] = h[n-1] * (a * n - b) / (n + c) abc枚举一下就出来了。
这题难点还是求逆元,因为有分母取模,而且m和i+1不一定互质。
所以分开考虑,因素分解m,然后得到m的素因子 记入map中,每次分解i+1的时候,判断这个因子是不是在map中出现过就行了。出现过记录,没出现过的部分就是和m互质的部分直接相乘取模就行了
//
// Created by Matrix on 2015-12-20
// Copyright (c) 2015 Matrix. All rights reserved.
//
//
//#pragma comment(linker, "/STACK:102400000,102400000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ALL(x) x.begin(), x.end()
#define INS(x) inserter(x, x,begin())
#define ll long long
#define CLR(x) memset(x, 0, sizeof x)
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int maxn = 1e5 + 10;
const int maxv = 1e3 + 10;
const double eps = 1e-9;
ll extended_gcd(ll a, ll b, ll &x, ll &y, ll& mod) {
if (b == 0) {
x = 1;
y = 0;
return a;
}
else {
ll gcd = extended_gcd(b, a % b, x, y, mod);
ll t = x % mod;
x = y % mod;
y = ((t - a/b*x) % mod + mod) % mod;
return gcd;
}
}
ll num[maxn];
map mp, vis;
map ::iterator iter;
ll fac[maxn], top;
void DivNum(ll n) {
top = 0;
for(ll i = 2; i * i <= n; i++) {
if(n % i == 0) {
fac[top] = i;
num[top] = 0;
while(n % i == 0) {
n /= i;
num[top]++;
}
top++;
}
}
if(n != 1) {
fac[top] = n;
num[top++] = 1;
}
}
int main() {
#ifdef LOCAL
freopen("in.txt", "r", stdin);
// freopen("out.txt","w",stdout);
#endif
// dp[0] = dp[1] = 1;
// for(int i = 2; i <= 1e5; i++) {
// dp[i] = dp[i-1] * (4 * i - 2) / (i + 1);
// }
ll n, m;
while(scanf("%lld%lld", &n, &m) != EOF && (n + m)) {
if(m == 1) {puts("0"); continue;}
mp.clear();
vis.clear();
ll st = 1 % m;
ll ans = st;
DivNum(m);
for(int i = 0; i < top; i++) {
vis[fac[i]]++;
}
for(ll i = 2; i <= n; i++) {
ll u = i * 4 - 2;
ll d = i + 1;
DivNum(u);
for(int j = 0; j < top; j++) {
if(vis.count(fac[j])) {
while(num[j]) {
u /= fac[j];
num[j]--;
mp[fac[j]]++;
}
}
}
DivNum(d);
for(int j = 0; j < top; j++) {
if(vis.count(fac[j])) {
while(num[j]) {
d /= fac[j];
num[j]--;
mp[fac[j]]--;
}
if(mp[fac[j]] == 0) mp.erase(fac[j]);
}
}
ll x, y;
extended_gcd(d, m, x, y, m);
st = st * u % m * x % m;
ll tmp = st;
for(iter = mp.begin(); iter != mp.end(); iter++) {
ll p = iter -> second;
ll ss = 1;
while(p--) {
ss = ss * (iter -> first) % m;
}
tmp = tmp * ss % m;
}
// printf("st = %lld\n", tmp);
ans = (ans + tmp) % m;
}
cout << ans << endl;
}
return 0;
}