# 【JZOJ5429】【NOIP2017提高A组集训10.27】排列

## Code

#include<iostream>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
const ll maxn=4e3+5,mo=1e9+7;
ll f[maxn][maxn],a[maxn],b[maxn],c[maxn],d[maxn],bz[maxn],g[maxn],p[maxn],ni[maxn],q[maxn],h[maxn];
ll n,m,i,t,j,k,l,x,y,z,ans;
ll mi(ll x,ll y){
if (y==1) return x;
t=mi(x,y/2);
if (y%2) return t*t%mo*x%mo;return t*t%mo;
}
ll pan(ll x,ll y){
return p[x]*ni[y]%mo*ni[x-y]%mo;
}
void make(int n){
f[0][0]=1;
for (i=1;i<=n;i++)
for (j=0;j<=i;j++)
f[i][j]=((j<i)*f[i-1][j]+(j!=0 && d[i]>=j)*f[i-1][j-1]*(d[i]-j+1)%mo)%mo;
for (i=n;i>=0;i--){
g[i]=f[n][i]*p[n-i]%mo;
for (j=i+1;j<=n;j++)
g[i]=(g[i]-pan(j,i)*g[j]%mo+mo)%mo;
}
}
int main(){
freopen("arrange.in","r",stdin);freopen("arrange.out","w",stdout);
scanf("%lld%lld",&n,&m);p[0]=1;
for (i=1;i<=n;i++)p[i]=p[i-1]*i%mo;
ni[n]=mi(p[n],mo-2);
for (i=n;i>=1;i--) ni[i-1]=ni[i]*i%mo;
for (i=1;i<=n;i++)scanf("%lld",&a[i]),bz[a[i]]++;
for (i=1;i<=n;i++)scanf("%lld",&b[i]),m-=(a[i]>b[i] && b[i]);
for (i=1;i<=n;i++)if (!a[i]) c[++c[0]]=b[i];j=0;
sort(c+1,c+c[0]+1);
for (i=1;i<=n;i++)if (!bz[i]){
while (i>c[j+1] && j<c[0]) j++;
d[++d[0]]=j;
}
make(d[0]);swap(q,g);
c[0]=d[0]=0;memset(bz,0,sizeof(bz));
for (i=1;i<=n;i++){
bz[b[i]]++;
if (!b[i]) h[++h[0]]=a[i];
}
for (i=1;i<=n;i++) if (!bz[i]) c[++c[0]]=i;j=0;
sort(h+1,h+h[0]+1);
for (i=1;i<=h[0];i++){
while (h[i]>c[j+1] && j<c[0]) j++;
d[i]=j;
}d[0]=h[0];
make(d[0]);
for (i=0;i<=m;i++)
ans=(ans+q[i]*g[m-i]%mo)%mo;
printf("%lld\n",ans);
}

• 广告
• 抄袭
• 版权
• 政治
• 色情
• 无意义
• 其他

120