默慈金数学习小记 && 51nod 1556 计算

49 篇文章 2 订阅
21 篇文章 0 订阅

参考博客:ACdreamers.

事实上默慈金数很偏门,据说早就渗入ACM竞赛中了(庆幸我才初中)。

默慈金数定义:

在一个圆上有n个不同的点,画出彼此互不相交弦的方案数(可以不画)即是第n个默慈金数。

递推公式:
M(1)=1,M(2)=2
M(n+1)=M(n)+n1i=0M(i)M(n1i)
神奇地可得:
M(n+1)=(2n+3)M(n)+3nM(n1)n+
转一下:
M(n)=(2n+1)M(n2)+(3n3)M(n2)n+2
便于记忆的形式:
M(n)=(2(n1)+3)M(n2)+(3(n2)+3)M(n2)n+2

证明我可不会,当然我也不想会,记住吧。

那么这个东西有什么用呢?

不知道为什么,第n项的默慈金数等于以下的东西:
在一个格子图中,从(0,0)出发,走n步,每次可以往右、右下或右上走,不能走到y=0以下的地方,走到(n,0)的方案数。

51nod 1556 计算.

这题和上面所讲的唯一不同的地方就是终点不一定是(n,0)。

这怎么办呢?

f(n) 表示n的答案。

假设现在走了n-1步,会停在0-n-1.

如果在(n-1,y)(y>0),则有三种走法,都是合法的。

如果在(n-1,0),则有两种走法,即向右上或向右,那么可以视作减去一个M(n-1).

所以 f(n)=f(n1)3M(n1)

Code:

#include<cstdio> 
#define ll long long
#define fo(i, x, y) for(ll i = x; i <= y; i ++)
using namespace std;

const ll mo = 1e9 + 7;

ll ksm(ll x, ll y) {
    ll s = 1;
    for(; y; y >>= 1, x = x * x % mo)
        if(y & 1) s = s * x % mo;
    return s;
}

ll n, M[1000005], f[1000005];

int main() {
    scanf("%lld", &n);
    M[1] = 1; M[2] = 2;
    f[1] = 1; f[2] = 2;
    fo(i, 3, n)
        M[i] = ((2 * i + 1) * M[i - 1] + (3 * i - 3) * M[i - 2]) % mo * ksm(i + 2, mo - 2) % mo,
        f[i] = (f[i - 1] * 3 - M[i - 2] + mo) % mo;
    printf("%lld", f[n]);
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值