【BZOJ 2024】 2024: [SHOI2009] 舞会 (容斥原理+高精度)

2024: [SHOI2009] 舞会

Time Limit: 10 Sec  Memory Limit: 64 MB
Submit: 368  Solved: 102

Description

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

Day2

 

 

【分析】

  这题高精度真是太可爱了。【然后我才发现如今大概只有我这种傻逼才会用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 }
View Code

 

2017-04-20 15:29:03

posted @ 2017-04-20 15:28  konjak魔芋  阅读(202)  评论(0编辑  收藏  举报