分析

我们可以假象一个假的限制 记录前 个条件都满足,但第 个条件不满足的方案数,考虑 之间的数随便排列, ,然后第 个条件不满足,前 个条件都满足,乘 ;对于不同的 ,方案是不相交的,且 计算了所有不应该在 中计数到的方案数所以 。思路来源与不知名的大佬。我这里只是分享一下做法。

代码

#include<bits/stdc++.h>
using namespace std;
int read() {
    int x = 0,f = 0;char ch = getchar();
    while(!isdigit(ch)) {if(ch=='-')f=1;ch=getchar();}
    while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    return f?-x:x;
}
const int N = 2100,mod = 20000311;
int f[N],p[N],n,m,fac[N];
int main() {
    n = read();m = read();
    fac[0] = 1;
    for(int i = 1;i <= n;i++) fac[i] = 1LL * fac[i-1] * i % mod;
    for(int i = 1;i <= m;i++) p[i] = read();
    p[++m] = n;sort(p+1,p+1+m);
    for(int i = 1;i <= m;i++) {
        f[i] = fac[p[i]];
        int res = 0;
        for(int j = 1;j < i;j++) {
            res = (res + 1LL * fac[p[i] - p[j]] * f[j]) % mod;
        }
        f[i] = ((f[i] - res) % mod + mod) % mod;
    }
    cout << f[m] << endl;
    return 0;
}