组合数学+费尔马小定理+快速幂
链接:https://ac.nowcoder.com/acm/contest/21791/G
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
空间限制: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 j≥i)。
每个数组包含 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 j≥i)。
输入描述:
第一行包含两个整数 n,m(2≤n≤m≤2⋅105)\ n,m (2≤n≤m≤2⋅10^5) n,m(2≤n≤m≤2⋅105)。
输出描述:
输出一个整数,表示满足上述所有条件的数组的数量,取模 998244353\ 998244353 998244353
备注:
原题链接: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; } }

浙公网安备 33010602011771号