组合数学+费尔马小定理+快速幂

链接:https://ac.nowcoder.com/acm/contest/21791/G
来源:牛客网

 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

你的任务是计算数组的数量,使得:

每个数组包含 n\ n n 个元素;
每个元素都是 1\ 1 1 m\ m m的整数;
对于每个数组,恰好有一对相等的元素;
对于每个数组 a\ a a,都存在一个索引 i\ i i,使得该数组在第 i\ i i 个元素之前严格升序并在它之后严格降序(形式上,这意味着 aj<aj+1\ a_j<a_{j+1} aj<aj+1,如果 j<i\ j<i j<i,并且 aj>aj+1\ a_j>a_{j+1} aj>aj+1,如果 j≥i\ j≥i ji)。

输入描述:

第一行包含两个整数 n,m(2≤n≤m≤2⋅105)\ n,m (2≤n≤m≤2⋅10^5) n,m(2nm2105)

输出描述:

输出一个整数,表示满足上述所有条件的数组的数量,取模 998244353\ 998244353 998244353
示例1

输入

复制
3 4

输出

复制
6

说明

6种序列是:
示例2

输入

复制
3 5

输出

复制
10
示例3

输入

复制
42 1337

输出

复制
806066790
示例4

输入

复制
100000 200000

输出

复制
707899035

备注:

原题链接:https://codeforces.com/problemset/problem/1312/D


本题解法思路如下:
1. 枚举相同的数以及最大数,举例如下:
如果两个相同的1,最大数为m时,结果为C(m-2,n-3)*2^(n-3),
累加和C(x-2,n-3)*2^(n-3)其中x的范围是从n-1到m。类似枚举2到m-1
记H[x]=C(x-2,n-3)*2^(n-3)。
容易得到
H[x]*(x-1)x从n-1到m累加,这个结果%M,可以得到最终答案。代码如下:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

    public static void main(String[] args) throws NumberFormatException, IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String[] words = br.readLine().split("\\s+");
        int n, m;
        n = Integer.valueOf(words[0]);
        m = Integer.valueOf(words[1]);
        if (n == 2) {
            System.out.println(0);
            return;
        }

        int M = 998244353;
        long[] H = new long[m + 1];
        System.out.println(cal(H, M, n, m));
    }

    /**
     * 计算pow(2,n)%M;
     * 
     * @param n
     * @param M
     * @return 这个结果
     */
    public static long powBase(int n, int M) {
        long ans = 1;
        if (n <= 2) {
            return (long) Math.pow(2, n);
        }
        long res = powBase(n / 2, M);
        if (n % 2 == 1) {
            return res * res % M * 2 % M;
        }
        return res * res % M;
    }

    public static long cal(long[] H, int M, int n, int m) {
        long first = powBase(n - 3, M);
        H[n - 1] = first;
        for (int x = n; x <= m; x++) {
            H[x] = H[x - 1] * (x - 2) % M * ferma(x - n + 1, M - 2, M) % M;
        }
        long ans = 0;
        for (int x = n - 1; x <= m; x++) {
            ans = ans + H[x] * (x - 1) % M;
            ans = ans % M;
        }
        return ans;
    }

    public static long ferma(long a, long n, int p) {
        if (n == 1) {
            return a % p;
        }
        if (n == 2) {
            return a * a % p;
        }
        long res = ferma(a, n / 2, p);
        if (n % 2 == 1) {
            return ((res * res % p) * a) % p;
        }
        return res * res % p;
    }

}

 

posted @ 2021-10-21 23:39  fishcanfly  阅读(85)  评论(1)    收藏  举报
//雪花飘落效果