zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Java核心技术卷阅读随笔--第5章【继承】
    Java核心技术卷阅读随笔--第4章【对象与类】
    Python创建虚拟环境
    软件工程实践2017第二次作业
    tf常见的损失函数(LOSS)总结
    python-Parser使用
    论文杂记
    最近看了Light-GCN的项目,记录了一些里面用到的api
    screen笔记
    Graph Convolutional Networks for Text Classification——论文笔记
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/12572953.html
Copyright © 2011-2022 走看看