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

京公网安备 11010502036488号