LG P4859 已经没有什么好害怕的了
Description
已经使 Madoka 有签订契约,和自己一起战斗的想法后,Mami 忽然感到自己不再是孤单一人了呢。
于是,之前的谨慎的战斗作风也消失了,在对 Charlotte 的傀儡使用终曲——Tiro Finale 后,Mami 面临着即将被 Charlotte 的本体吃掉的局面。
这时,已经多次面对过 Charlotte 的 Homura 告诉了学 OI 的你这样一个性质:Charlotte 的结界中有两种具有能量的元素,一种是“糖果”,另一种是“药片”,各有 $n$ 个。在 Charlotte 发动进攻前,“糖果”和“药片”会两两配对,若恰好糖果比药片能量大的组数比“药片”比“糖果”能量大的组数多 $k$ 组,则在这种局面下,Charlotte 的攻击会丟失,从而 Mami 仍有消灭 Charlotte 的可能。
你必须根据 Homura 告诉你的“糖果”和“药片”的能量的信息迅速告诉 Homura 这种情况的个数.
Solution
首先两数组升序排序,记$num_i$为$a_i$比$b$中多少元素大,$f_{i,j}$为从$a$中选$i$个,再从这$i$个中选$j$个,再从$b$中选择$j$个使$a_k > b_k$的方案数
$$f_{i,j}=f_{i-1,j}+f_{i-1,j-1}(num_j-j+1)$$
设$g_i$表示刚好选出$i$组满足$a_k > b_k$的方案数
$$g_i=f_{n,i}-\sum_{j=i+1}^n g_j\binom{j}{i}$$
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<algorithm> #include<iostream> #include<cstdio> using namespace std; int n,k,a[2005],b[2005],num[2005]; long long f[2005][2005],fac[2005]={1},inv[2005],g[2005]; const long long mod=1e9+9; inline int read() { int f=1,w=0; char ch=0; while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') w=(w<<1)+(w<<3)+ch-'0',ch=getchar(); return f*w; } long long ksm(long long a,long long p) { long long ret=1; while(p) { if(p&1) (ret*=a)%=mod; (a*=a)%=mod,p>>=1; } return ret; } long long C(int x,int y) { if(y>x||x<0||y<0) return 0; return fac[x]*inv[y]%mod*inv[x-y]%mod; } int main() { for(int i=1;i<=2000;i++) fac[i]=fac[i-1]*i%mod; inv[2000]=ksm(fac[2000],mod-2); for(int i=1999;~i;i--) inv[i]=inv[i+1]*(i+1)%mod; n=read(),k=read(); if((n-k)&1) return puts("0"),0; k+=((n-k)>>1); for(int i=1;i<=n;i++) a[i]=read(); for(int i=1;i<=n;i++) b[i]=read(); sort(a+1,a+n+1),sort(b+1,b+n+1); for(int i=1,pos=1;i<=n;i++) { while(b[pos]<a[i]&&pos<=n) ++pos; num[i]=pos-1; } for(int i=0;i<=n;i++) f[i][0]=1; for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) f[i][j]=(f[i-1][j]+1ll*f[i-1][j-1]*(num[i]-j+1)%mod)%mod; for(int i=n;i>=k;i--) { g[i]=f[n][i]*fac[n-i]%mod; for(int j=n;j>i;j--) (((g[i]-=g[j]*C(j,i)%mod)%=mod)+=mod)%=mod; } printf("%lld\n",g[k]); return 0; }