E - 最值区间计数

题目链接:

题目大意:

求出长度为 n n n 的所有排列中所有最大值为 n n n 且最小值为 1 1 1 的子区间个数,对 998244353 998244353 998244353 取模。

思路:

1 1 1 的位置为 i i i n n n 的位置为 j j j,也就是求 2 ∗ ( n − 2 ) ! ∗ ∑ i = 1 n ∑ j = i + 1 n i ∗ ( n − j + 1 ) 2*(n-2)!*\sum_{i=1}^n\sum_{j=i+1}^ni*(n-j+1) 2(n2)!i=1nj=i+1ni(nj+1).
对于 ∑ i = 1 n ∑ j = i + 1 n i ∗ ( n − j + 1 ) 相当于 ∑ i = 1 n ∑ j = i + 1 n ( n ∗ i − j ∗ i + i ) . 对于\sum_{i=1}^n\sum_{j=i+1}^ni*(n-j+1)相当于 \sum_{i=1}^n\sum_{j=i+1}^n(n*i-j*i+i). 对于i=1nj=i+1ni(nj+1)相当于i=1nj=i+1n(niji+i).
等于 ∑ i = 1 n ( ∑ j = i + 1 n n ∗ i + ∑ j = i + 1 n i − ∑ j = i + 1 n j ∗ i ) . 等于 \sum_{i=1}^n( \sum_{j=i+1}^nn*i + \sum_{j=i+1}^ni- \sum_{j=i+1}^nj*i). 等于i=1n(j=i+1nni+j=i+1nij=i+1nji).
即 ∑ i = 1 n ( ( n − i ) ∗ ( n ∗ i + i ) − i ∑ j = i + 1 n j ) . 即\sum_{i=1}^n( (n-i)*(n*i + i)- i\sum_{j=i+1}^nj). i=1n((ni)(ni+i)ij=i+1nj).
也就是 ∑ i = 1 n ( ( n − i ) ∗ ( n ∗ i + i ) − i ∗ ( i + 1 + n ) ∗ ( n − i ) 2 ) . 也就是\sum_{i=1}^n( (n-i)*(n*i + i)- i * \frac {(i+1 + n)*(n - i)}{2}). 也就是i=1n((ni)(ni+i)i2(i+1+n)(ni)).
处理出 ( n − 2 ) ! (n-2)! (n2)! 代入公式求解即可,注意取模。(这里需特判 n = 1 n=1 n=1 的情况)

代码:

#include <bits/stdc++.h>
#define int long long
const int N = 1e5 + 10, mod = 998244353;
using namespace std;
using LL = long long;

signed main() {
    int n;
    cin >> n;
    if (n == 1)
        cout << 1;
    else {
        int val = 1;
        for (int i = 1; i <= n - 2; i++) val = (val * i) % mod;
        int ans = 0;
        for (int i = 1; i <= n; i++) {
            ans = (ans + (n - i) * (n * i + i) - i * (i + 1 + n) * (n - i) / 2) % mod;
        }
        cout << 2 * val * ans % mod;
    }
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值