*题解:CF1284C New Year and Permutation
解析
首先可以发现框定段 \([l,r]\) 满足如果将该区间内的数从小到大排列,则最终得到的序列连续。
考虑如何求一个给定序列的框定段个数,这其实是 P8600,对正解并没有启发。
正难则反,考虑对于所有长度为 \(x\) 的框定段,包含它的排列个数。段内元素有 \(n - x + 1\) 种选择,段内排列有 \(x!\) 种,段外排列有 \((n - x)!\) 种,段的可选位置有 \(n - x + 1\) 个,全部乘起来即为所求。每个长度的结果加起来即为答案。
时间复杂度 \(O(n)\)。
代码
/*
*/
#include <bits/stdc++.h>
#define eps 0.0000000001
#define ls(x) ((x) << 1)
#define rs(x) (((x) << 1) | 1)
#define mid ((l + r) >> 1)
using namespace std;
typedef long long ll;
typedef unsigned ui;
typedef pair<ll, ll> pii;
const int N = 2.5e5 + 5, M = 20, P = 450, mod = 998244353, mod2 = 1e9 + 7, b1 = 131;
int fac[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
int n,m;
cin>>n>>m;
fac[0] = 1;
for(int i=1;i<=n;i++){
fac[i] = 1ll * fac[i - 1] * i % m;
}
int res = 0;
for(int x=1;x<=n;x++){
res = (res + 1ll * (n - x + 1) * (n - x + 1) % m * fac[x] % m * fac[n - x] % m) % m;
}
cout<<res;
return 0;
}

浙公网安备 33010602011771号