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

来源:互联网 发布:淘宝钻展要多少钱 编辑:程序博客网 时间:2024/06/18 20:16
【题目描述】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;}


原创粉丝点击