【BZOJ 2024】 2024: [SHOI2009] 舞会 (容斥原理+高精度)
2024: [SHOI2009] 舞会
Time Limit: 10 Sec Memory Limit: 64 MB
Submit: 368 Solved: 102Description
OItown要举办了一年一度的超级舞会了,作为主办方的Constantine为了使今年的舞会规模空前,他邀请了许多他的好友和同学去。舞会那天,恰好来了n个男生n个女生。Constantine发现,一般情况下,舞伴之间,总是男伴总是比女伴长得高,不过,偶尔也是有特殊情况的。所以,Constantine现在想知道,如果把这2n个人恰好配成n对舞伴,有多少种搭配方法,而且他要求最多只有k对舞伴之间女伴比男伴高。现在,Constantine需要参加SHTSC的你帮助他算出这个答案,当然啦,他会先告诉你这2n个同学的身高。
Input
第一行:两个整数n、k,含义如问题中所示。 第2行到第n+1行:n个整数,表示n个男生的身高。第n+2行到第2n+1行:n个整数,表示n个女生的身高。表示身高的正整数,都不超过 。
Output
输出文件只有一个,即满足n对舞伴中最多只有k对舞伴之间女伴比男伴高的男女搭配方案数。
Sample Input
3 0
178
188
176
168
178
170
Sample Output
4
评分
如果你的输出文件与标准答案完全相符,你将获得该测试点的全部分数,否则得零分。
N< = 200
K< = N
HINT
Source
【分析】
这题高精度真是太可爱了。【然后我才发现如今大概只有我这种傻逼才会用10进制的高精度,别人都是4位4位做的,搞的我RE,0msTLE,MLE都试了一通。。
然后就是,跟“已经没有什么好害怕了”无异,具体可以看那篇。
对于至多k,而不是恰好k,就分成恰好0+恰好1+。。。+恰好k就好了。
【再表示一下用结构体重载运算符写高精度真的好看很多】
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 210 8 #define Maxl 210 9 #define Mod 10000 10 11 int a[Maxn],b[Maxn],mx[Maxn]; 12 13 struct hugeint 14 { 15 int w[Maxl],l; 16 hugeint() {memset(w,0,sizeof(w));l=0;} 17 friend hugeint operator + (hugeint x,hugeint y) 18 { 19 x.l=max(x.l,y.l); 20 for(int i=0;i<=x.l;i++) x.w[i]=x.w[i]+y.w[i]; 21 for(int i=0;i<=x.l;i++) x.w[i+1]+=x.w[i]/Mod,x.w[i]%=Mod; 22 while(x.w[x.l+1]!=0) x.w[x.l+2]+=x.w[x.l+1]/Mod,x.w[++x.l]%=Mod; 23 while(x.w[x.l]==0&&x.l>1) x.l--; 24 return x; 25 } 26 friend hugeint operator - (hugeint x,hugeint y) 27 { 28 for(int i=0;i<=x.l;i++) x.w[i]=x.w[i]-y.w[i]; 29 for(int i=0;i<=x.l;i++) if(x.w[i]<0) x.w[i]+=Mod,x.w[i+1]--; 30 while(x.w[x.l]==0&&x.l>0) x.l--; 31 return x; 32 } 33 friend hugeint operator * (hugeint x,hugeint y) 34 { 35 hugeint ret;ret.l=x.l+y.l; 36 for(int i=0;i<=x.l;i++) for(int j=0;j<=y.l;j++) ret.w[i+j]+=x.w[i]*y.w[j]; 37 for(int i=0;i<=ret.l;i++) ret.w[i+1]+=ret.w[i]/Mod,ret.w[i]%=Mod; 38 while(ret.w[ret.l+1]!=0) ret.w[ret.l+2]+=ret.w[ret.l+1]/Mod,ret.w[++ret.l]%=Mod; 39 while(ret.w[ret.l]==0&&x.l>0) ret.l--; 40 return ret; 41 } 42 friend hugeint operator * (hugeint x,int y) 43 { 44 for(int i=0;i<=x.l;i++) x.w[i]*=y; 45 for(int i=0;i<=x.l;i++) x.w[i+1]+=x.w[i]/Mod,x.w[i]%=Mod; 46 while(x.w[x.l+1]!=0) x.w[x.l+2]+=x.w[x.l+1]/Mod,x.w[++x.l]%=Mod; 47 while(x.w[x.l]==0&&x.l>0) x.l--; 48 return x; 49 } 50 friend bool operator > (hugeint x,hugeint y) 51 { 52 if(x.l!=y.l) return x.l>y.l; 53 for(int i=x.l;i>=0;i++) 54 { 55 if(x.w[i]!=y.w[i]) return x.w[i]>y.w[i]; 56 } 57 } 58 }; 59 hugeint f[2][Maxn],c[Maxn][Maxn],fac[Maxn],g[Maxn]; 60 void clear(hugeint &x) {memset(x.w,0,sizeof(x.w));x.l=0;} 61 62 int main() 63 { 64 int n,k; 65 scanf("%d%d",&n,&k); 66 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 67 for(int i=1;i<=n;i++) scanf("%d",&b[i]); 68 sort(a+1,a+1+n);sort(b+1,b+1+n); 69 mx[0]=0; 70 for(int i=1;i<=n;i++) 71 { 72 mx[i]=mx[i-1]; 73 while(b[i]>a[mx[i]+1]&&mx[i]<n) mx[i]++; 74 } 75 f[0][0].w[0]=f[1][0].w[0]=1; 76 for(int i=1;i<=n;i++) 77 { 78 int p=i&1,pp=p^1; 79 for(int j=1;j<=i;j++) 80 { 81 f[p][j]=f[pp][j]+f[pp][j-1]*max(mx[i]-j+1,0); 82 } 83 } 84 for(int i=0;i<=n;i++) c[i][0].w[0]=1; 85 for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) c[i][j]=c[i-1][j-1]+c[i-1][j]; 86 hugeint a1,a2,ans; 87 fac[0].w[0]=1; 88 for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i; 89 for(int i=0;i<=n;i++) g[i]=f[n&1][i]*fac[n-i]; 90 for(int i=0;i<=k;i++) 91 { 92 clear(a1);clear(a2); 93 for(int j=n;j>=i;j--) 94 { 95 if((j-i)&1) a2=a2+g[j]*c[j][i]; 96 else a1=a1+g[j]*c[j][i]; 97 if(a1>a2) {a1=a1-a2;clear(a2);} 98 } 99 ans=ans+(a1-a2); 100 } 101 printf("%d",ans.w[ans.l]); 102 for(int i=ans.l-1;i>=0;i--) printf("%04d",ans.w[i]);printf("\n"); 103 return 0; 104 }
2017-04-20 15:29:03