#C231114A. 平凡(ordinary)
前言(Front talk)
网址(Website)
题目(Problem)
对于一个排列
是 的子序列。 。
现在给定
由于答案可能很大, 你只用输出答案
输入格式
从文件
第一行两个整数
第二行
保证
输出格式
输出一行,一个整数,表示
样例
输入数据 1
3 2
1 2
输出数据 1
0
输入数据 2
10 5
2 7 8 3 6
输出数据 2
30240
【样例
见选手目录下的
数据规模与约定
对于
保证
本题使用打包测评。各子任务的附加限制及分值如下表所示:
子任务编号 | 附加限制 | 分值 |
---|---|---|
无特殊限制 |
题解(Solution)
代码(Code)
#include<bits/stdc++.h>
#define For(i,l,r) for(int i=l;i<=r;i++)
#define Rof(i,l,r) for(int i=l;i>=r;i--)
using namespace std;
#define int long long
inline int input(){int x;return cin>>x,x;}
const int inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
const int N = 1012345;
int n,m,a[N];
bitset<N> fix,vst;
signed main(){
freopen("ordinary.in","r",stdin);
freopen("ordinary.out","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>m;
int p=1,ans=1,pos=0;
for(int i=m+1;i<=n;i++) p=p*i%mod;
for(int i=1;i<=m;i++){
a[i]=input();
if(vst[a[i]]) return cout<<'0',0;vst[a[i]]=true;
}for(int i=1;i<=m;i++)
if(a[i]>a[i+1]){pos=i;for(int j=i+1;j<=n;j++) fix[a[j]]=true;break;}
a[m+1]=inf;
for(int i=1,sum=0;i<=n;i++)
if(!fix[i]){//如果当前的值不在pos后面
//当且仅当不在a[i]中时有答案(当前值大于a[pos]的值时可以放在a[pos]的前面(否则放在a[pos]前面就是当前值更优了)
if(!vst[i]) ans=ans*(sum+(i>a[pos]))%mod;
sum++;//大的数只能放在小的数后面,sum记录的是小的数的个数
}
cerr<<ans<<'\n';
cout<<(p-ans+mod)%mod<<'\n';
return 0;
}