NC20416. [SHOI2009] 舞会
描述
输入描述
第一行:两个整数n、k,含义如问题中所示。 第2行到第n+1行:n个整数,表示n个男生的身高。第n+2行到第2n+1行:n个整数,表示n个女生的身高。表示身高的正整数,都不超过 。
输出描述
输出文件只有一个,即满足n对舞伴中最多只有k对舞伴之间女伴比男伴高的男女搭配方案数。
示例1
输入:
3 0 178 188 176 168 178 170
输出:
4
C++11(clang++ 3.9) 解法, 执行用时: 108ms, 内存消耗: 31468K, 提交时间: 2020-05-13 18:45:54
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; #define N 205 int n,k,now; int boy[N],girl[N]; struct data{int a[N],len,f;}zero,one,ans,c[N][N],f[2][N],mul[N]; data jian(data a,data b) { data ans=zero;int len=max(a.len,b.len); if (a.len<b.len) ans.f=-1,swap(a,b); else if (a.len==b.len) { for (int i=len;i>=1;--i) if (a.a[i]>b.a[i]) break; else if (a.a[i]<b.a[i]) { ans.f=-1; swap(a,b); break; } } for (int i=1;i<=len;++i) { if (a.a[i]<b.a[i]) { --a.a[i+1]; a.a[i]+=10000; } ans.a[i]=a.a[i]-b.a[i]; } while (len>1&&!ans.a[len]) --len; ans.len=len; if (ans.len==1&&ans.a[1]==0) ans.f=1; return ans; } data jia(data a,data b) { data ans=zero; if (a.f!=b.f) { if (a.f==1) { b.f=1; return jian(a,b); } else { a.f=1; return jian(b,a); } } ans.f=a.f; int len=max(a.len,b.len); for (int i=1;i<=len;++i) ans.a[i]=a.a[i]+b.a[i]; for (int i=1;i<=len;++i) { ans.a[i+1]+=ans.a[i]/10000; ans.a[i]%=10000; } if (ans.a[len+1]) ++len; ans.len=len; if (ans.len==1&&ans.a[1]==0) ans.f=1; return ans; } data cheng(data a,data b) { int len=a.len+b.len-1; data ans=zero;ans.f=(a.f==b.f)?1:-1; for (int i=1;i<=a.len;++i) for (int j=1;j<=b.len;++j) ans.a[i+j-1]+=a.a[i]*b.a[j]; for (int i=1;i<=len;++i) { ans.a[i+1]+=ans.a[i]/10000; ans.a[i]%=10000; } while (ans.a[len+1]) { ++len; ans.a[len+1]+=ans.a[len]/10000; ans.a[len]%=10000; } ans.len=len; if (ans.len==1&&ans.a[1]==0) ans.f=1; return ans; } void print(data a) { if (a.f==-1) putchar('-'); for (int i=a.len;i>=1;--i) { if (i==a.len||a.a[i]>=1000) printf("%d",a.a[i]); else if (a.a[i]>=100) printf("0%d",a.a[i]); else if (a.a[i]>=10) printf("00%d",a.a[i]); else printf("000%d",a.a[i]); } puts(""); } void init() { zero.len=1,zero.f=1;one.len=one.a[1]=one.f=1; mul[0]=one; for (int i=1;i<=n;++i) { data x=zero;x.a[1]=i; mul[i]=cheng(mul[i-1],x); } for (int i=0;i<=n;++i) c[i][0]=one; for (int i=1;i<=n;++i) for (int j=1;j<=n;++j) c[i][j]=jia(c[i-1][j],c[i-1][j-1]); } int main() { scanf("%d%d",&n,&k); init(); for (int i=1;i<=n;++i) scanf("%d",&boy[i]); for (int i=1;i<=n;++i) scanf("%d",&girl[i]); sort(boy+1,boy+n+1);sort(girl+1,girl+n+1); for (int i=0;i<=1;++i) for (int j=0;j<=n;++j) f[i][j]=zero; for (int i=0;i<=1;++i) f[i][0]=one; now=0; for (int i=1;i<=n;++i) { while (now<n&&boy[now+1]<girl[i]) ++now; for (int j=1;j<=i;++j) { f[i&1][j]=f[(i-1)&1][j]; data x=zero;x.a[1]=now-j+1; x=cheng(f[(i-1)&1][j-1],x); if (now>j-1) f[i&1][j]=jia(f[i&1][j],x); } } ans=zero; for (int i=0;i<=k;++i) for (int j=i,opt=1;j<=n;++j,opt=-opt) { data x=f[n&1][j]; x=cheng(x,mul[n-j]);x=cheng(x,c[j][i]); if (opt==-1) x.f=-x.f; ans=jia(ans,x); } print(ans); }