zoukankan      html  css  js  c++  java
  • 有趣的数(组合计数,CCF)

    题意

    我们把一个数称为有趣的,当且仅当:

    • 它的数字只包含 (0,1,2,3),且这四个数字都出现过至少一次。
    • 所有的 (0) 都出现在所有的 (1) 之前,而所有的 (2) 都出现在所有的 (3) 之前。
    • 最高位数字不为 (0)

    因此,符合我们定义的最小的有趣的数是 (2013)

    除此以外,(4) 位的有趣的数还有两个:(2031)(2301)

    请计算恰好有 (n) 位的有趣的数的个数。

    由于答案可能非常大,只需要输出答案除以 (10^9+7) 的余数。

    数据范围

    (4 leq n leq 1000)

    思路

    感觉这道题的题目描述挺像高中数学排列组合题的,因此先考虑组合计数方法。

    组合计数题通常的思考方式就是分类讨论。这道题可以将(0,1)看成一组,(2,3)看成一组,一组的数量确定了,另一组的数量也就跟着确定了。

    因此,我们可以分类讨论(0,1)组的数量。因为每个数组都至少出现过(1)次,因此(0,1)组的数量可以是(2 sim n - 2)中的任意数。

    假设数量是(k),那么就从(n - 1)位(第一位不能选)选(k)位,因此就是(C_{n - 1}^k)种。

    然后再讨论每个数具体个数,那么(0)可能有(1 sim k - 1),因此就有(k - 1)种情况;对应的,(2)可能有(1 sim n - k - 1),因此就有(n - k - 1)种可能。

    因此,最终的答案为:

    [sum_{k = 2}^{n - 2} C_{n - 1}^k * (k - 1) * (n - k - 1) ]

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    typedef long long ll;
    
    const int N = 1010, mod = 1e9 + 7;
    
    int n;
    ll c[N][N];
    
    int main()
    {
        scanf("%d", &n);
        for(int i = 0; i <= n; i ++) {
            for(int j = 0; j <= i; j ++) {
                if(!j) c[i][j] = 1;
                else c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
            }
        }
        ll ans = 0;
        for(int i = 2; i <= n - 2; i ++) {
            ans = (ans + c[n - 1][i] * (i - 1) * (n - i - 1)) % mod;
        }
        printf("%lld
    ", ans);
        return 0;
    }
    
  • 相关阅读:
    Windows XP下Qemu模拟器上OpenSolaris的安置
    图解SMC下Solaris用户图形经管(下)
    Solaris 10的功能
    在Solaris 下用DVD光盘保存数据(1)
    Solaris10下载、安设和设置装备摆设(2)
    Solaris 10密码忘记打点法子
    对Unix任事器进行性能监测(上)
    Solaris效力打点东西 SMF快速入门指南(3)
    Solaris 10主动安顿DVD运用步骤
    Solaris效劳经管器材 SMF疾速入门指南(2)
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/14511285.html
Copyright © 2011-2022 走看看