HDU3240题解

来源:互联网 发布:即时消息软件 编辑:程序博客网 时间:2024/05/17 05:16

分析:一看就知道是卡特兰数
卡特兰数的公式:
令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 <algorithm>#include <cctype>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <iomanip>#include <iostream>#include <map>#include <queue>#include <string>#include <sstream>#include <set>#include <vector>#include <stack>#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 <ll, ll> mp, vis;map <ll, ll>::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;}
0 0
原创粉丝点击