【Catalan数】【同余】【SCOI2010】字符串

本博客探讨了一个生成包含n个1和m个0的字符串问题,要求字符串前k个字符中1的数量不少于0的数量。通过解析Catalan数的应用及分数求模运算,我们得出了解决此类问题的方法,并提供了具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

【题目描述】
lxhgww最近接到了一个生成字符串的任务,任务需要他把n个1和m个0组成字符串,但是任务还要求在组成的字符串中,在任意的前k个字符中,1的个数不能少于0的个数。现在lxhgww想要知道满足要求的字符串共有多少个,聪明的程序员们,你们能帮助他吗?
【输入】
输入数据是一行,包括2个数字n和m
【输出】
输出数据是一行,包括1个数字,表示满足要求的字符串数目,这个数可能会很大,只需输出这个数除以20100403的余数
【样例输入】
2 2
【样例输出】
2
【数据范围】
对于30%的数据,保证1<=m<=n<=1000
对于100%的数据,保证1<=m<=n<=1000000

此题考察Catalan数的应用以及分数求模运算。

如图所示,证明此问题的解为:
           ╭ m        ╭ m - 1
f(n, m) =  │        - │
           ╰ n + m    ╰ n + m
           (n - m + 1) (n + m)!
        = ───────────
               (n + 1)!  m!
                            ╭ m
首先,n个1,m个0自由组合,有│       种。
                            ╰ n + m


接下来可作如下转化:
将每个1对应坐标变换(1, 1),每个0对应坐标变换(1, -1)。
可行的方案为:从(0, 0)通过以上两种坐标变换达到(n + m, n - m),但不能向下越过x轴。
对于不可行的方案总数,如图所示,由于每个不可行的方案必定经过直线y = -1,所以将线路与y = -1最左边的交点向左的部分
沿直线y = -1向下翻折,则不可行的方案总数就变成了:
求从从(0, -2)通过以上两种坐标变换达到(n + m, n - m)的方案总数,即:
╭ m - 1
│       。
╰ n + m

令MOD = 20100403,则原问题的解为:
         (n - m + 1) (n + m)!
 ans ≡ ─────────── (mod MOD)
             (n + 1)!  m!
由分数取模的定义,可得:
            (n - m + 1) (n + m)!
 m! ans ≡ ─────────── (mod MOD)
                  (n + 1)!
算出右式,并在[0, MOD)范围内枚举ans,
再输出满足条件的ans的值即可。

另:由费马小定理,可得:

         (n - m + 1) (n + m)!
 ans ≡ ─────────── ·(m!)^(MOD - 2)  (mod MOD)
               (n + 1)!

Accode:

#include <fstream>
int main()
{
    std::ifstream fin("string.in");
    std::ofstream fout("string.out");
    typedef long long int64;
    const int64 MOD = 20100403;
	int64 n, m, ans;
	fin >> n >> m;
	int64 numer = n - m + 1;
	for (int64 i = n + 2; i < n + m + 1; ++i)
        (numer *= i) %= MOD;
    int64 denom = 1;
    for (int64 i = 2; i < m + 1; ++i)
        (denom *= i) %= MOD;
    for (ans = 0; ans < MOD; ++ans)
        if ((denom * ans) % MOD == numer)
            break;
    fout << ans << std::endl;
    fin.close(); fout.close();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值