• Codeforces


    题目链接
    题目大意:让你从(m)个数里面挑出来若干个数构成一个(n)个数的序列,且这个序列有且仅有一对相等的数。并且,这个序列在一个数字之前严格单调递增,在同一个数字之后严格单调递减。问你最多能组成多少个这样的序列。
      首先,题目已经告诉我们了,我们要求的序列是一个单峰序列,所以如果(n=2)的话是不能构成这样的序列的(坑点)。
      然后我们开始分析,要构成一个含有(n)个数并且有且只有一对数字重复的序列需要(n-1)个数,所以选法一共有(C{{n-1}atop{m}})种,对于这(n-1)个数,因为是单峰的,所以最大的数的位置一定是固定不变的,又要左右两边分别严格单调,所以位置也不能变。所以,能重复出现的数字一共有(n-2)种。最后我们还要考虑左右数字移动的问题。因为相等的数字不能出现在同一边,而且最大的数不能动,所以就只有(n-3)个数可以动,因为这(n-3)个数字都不相同,显然,它们中的任意一个数都能移动到另一边。那么对于(n-3)个数字中的每一个数都有在某一边和不在某一边两种情况,也就是(2^{n-3})种情况。
      综上所述,我们的答案就是(C{{n-1}atop{m}} imes (n-2) imes 2^{n-3}),这里组合数比较大,所以我们取模的时候需要用到逆元的知识,然后用快速幂求解即可。

    ll qpow(ll x, int y) {
        ll res = x, ans = 1;
        while(y) {
            if (y&1) ans = ans*res%MOD;
            res = res*res%MOD;
            y >>= 1;
        }
        return ans;
    }
    int main(void) {
        ll n, m;
        while(~scanf("%lld%lld", &n, &m)) {
            if (n==2) {
                printf("0
    ");
                continue;
            }
            ll fac1 = 1, fac2 = 1;
            for (int i = m; i>m-n+1; --i)
                fac1 = fac1*i%MOD;
            for (int i = n-1; i>1; --i)
                fac2 = fac2*i%MOD;
            printf("%lld
    ", fac1*qpow(fac2, MOD-2)%MOD*(n-2)%MOD*qpow(2, n-3)%MOD);
        }
        return 0;
    }
    
  • 相关阅读:
    Linux下查找文件(find、grep命令)及结合使用
    Linux x86 Program Start Up
    signal 信号具体含义解释(转)
    迁移Go mod使用笔记
    JS 中几种常用的循环方式
    JS 简单的表单验证功能
    微信小程序中的less开发公共样式引入
    vueelementadmin 超过两级嵌套路由无法缓存的解决办法
    PLM数据库脚本升级命令
    Git中的AutoCRLF与SafeCRLF
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/12572953.html
Copyright © 2020-2023  润新知