https://ac.nowcoder.com/acm/contest/7745/C
给了m个条件,每个条件代表序列前a[i]个不能是1-a[i]的全排列;
因为如果直接用所有的情况去见减会出现重复,dp[i]代表在当前情况下不合法的数量且和之前没有重复情况的数量。对于dpi,所有的不合法情况是ai!,对于每一个a[i-k],(k<i),同时满足两个条件的个数是dp[i-k]*(i到k的距离的阶乘),最后ans就是全体的阶乘减去(每个dp乘他们到末尾距离的阶乘)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i, x, n) for (ll i = x; i <= n; i++)
#define per(i, x, n) for (ll i = x; i >= n; i--)
const int maxn = 3e5 + 100;
ll mod = 20000311;
ll jc[maxn];
int a[maxn],f[maxn],m,n;
int main(){
cin >> n >> m;
jc[1] = 1;
rep(i, 2, 3000) jc[i] = i * jc[i - 1] % mod;
rep(i, 1, m) cin >> a[i];
sort(a + 1, a + 1 + m);
f[1] = jc[a[1]];
rep(i,1,m)//fi=第i个条件下不合法的情况数减去和i之前的限制重合的情况
{
f[i] = jc[a[i]];
for (int j = 1; j < i;j++)
{
f[i] -= f[j] * jc[a[i] - a[j]] % mod;
if(f[i] < 0)
f[i] += mod;
}
}
ll ans = jc[n];
rep(i,1,m)
{
ans -= f[i] * jc[n - a[i]] % mod;
if(ans<0)
ans += mod;
}
cout << ans;
}