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;
    }
    
  • 相关阅读:
    深度学习中一些常用函数的偏导数
    C++ 隐式类型转换与类型转换函数
    Tensorboard数据(tfevents文件)格式解析及ofstream使用问题
    记一次由unordered_map引起的bug
    softmax数值溢出 与 xent-loss问题
    C++ 单独编译(separate compilation)与 模板的编译
    TensorFlow源码分析——Tensor与Eigen
    ubuntu16.04 docker tensorflow-gpu镜像使用
    vscode Ftp-sync插件报错问题: sync error: Error: Permission denied
    PHP加速之eaccelerator
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/14511285.html
Copyright © 2011-2022 走看看