算法竞赛进阶指南0x36组合计数

概述

在这里插入图片描述
在这里插入图片描述

AcWing211. 计算系数

在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
const int mod = 10007 ;
int ksm(int a, int b, int p)
{
    int ans = 1%p;
    a = a%p;
    while(b)
    {
        if(b&1) ans = (long long)ans * a % p;
        a = (long long)a*a%p;
        b>>=1;
    }
    return ans;
}
int jie(int n)
{
    int ans = 1;
    for(int i = 1; i <= n; i++)
    {
        ans = (long long)ans * i %mod;
    }
    return ans;
}
int niyuan(int x)
{
    return ksm(x, mod-2, mod);
}

int main()
{
    int a,b,k,n,m;
    cin >> a >> b >> k >> n >> m;
    int fenzi = jie(k);
    int fenmu = jie(k-m)*jie(m) % mod;
    int CC = fenzi * niyuan(fenmu)%mod;
    int asn = ksm(a, n, mod)*ksm(b, m, mod)%mod*CC%mod;
    printf("%d", asn);
    return 0;
}

多重集

在这里插入图片描述

AcWing212. 计数交换

在这里插入图片描述
在这里插入图片描述

Lucas定理

古代猪文

先对合数进行分解的代码:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    int x = 999911658;
    for(int i = 2; (long long)i*i <= x; i++)
    {
        if(x % i==0)
        {
            printf("%d\t", i);
            int cnt = 0;
            while(x%i==0)
            {
                x /= i;
                cnt ++;
            }
            printf("%d\n", cnt);
        }
    }
    if(x > 1)
    printf("%d\t1\n", x);
    return 0;
}

运行结果

2	1
3	1
4679	1
35617	1

Catalan定理

证明如下:
证明要点:

  • 从反方向来进行考虑
  • 把一个不好计数的集合与一个已知的可计数的集合建立一一映射

容易得到:
总共有 C 2 n n C^n_{2n} C2nn 种情况。
现在思考不成立的情况:
建立映射:

P(不合法情况集合)Q(有n-1个0,n+1个1)
找到一个最短的前缀,不满足条件。(这个前缀里面有1的个数比0的个数多1) 然后把其他部分取反,得到q同左,找到最短的前缀,使得前缀里面有1的个数比0的个数多1 然后把后面取反

容易证明:
已知一个不合法的原情况,可以映射到Q。
而在Q中,也可以映射到P。
说明两个集合相互包含,进而得到两个集合相等。
故个数相等。
所以不合法的情况有 C 2 n n − 1 C^{n-1}_{2n} C2nn1 种。
相减,得到Katalan数列的个数。
C 2 n n n + 1 {C^{n}_{2n}}\over{n+1} n+1C2nn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值