已经没有什么好害怕的了——二项式反演+经典套路
题面:已经没有什么好害怕的了
首先,大k个,k=(n+k)/2,糖果多的恰好有k组
一个通用技巧是:
找到两个数组f,g
f范围宽松好统计,g范围严格难统计但是和答案有直接关系,
这样,只要得到f和g的关系,就可以找到答案!
经常是可以得到f由g的表达式,然后斯特林反演或者二项式反演得到g的求法
也可以用多项式科技
数论函数的反演也可以这么做。
这个题就这样做:
涉及大小关系,先把A,B从小到大排序便于决策
称糖果比药片大的配对叫“优秀”
设f[k]表示,“钦定选择k组优秀,其他任意选”方案数。
g[k]表示,“恰好k组优秀”。g[K]就是答案
f和g的关系式:
$f[i]=\sum_{j=i}^nC(j,i)g[j]$
二项式反演:
$g[i]=\sum_{j=i}^n(-1)^{j-i}C(j,i)*f[j]$
任意选择i个都构成一组钦定。
计算f
DP,$f[i][j]$前i个,钦定了j个
$f[i][j]=f[i-1][j]+f[i-1][j-1]*(small[i]-(j-1))$
第i个选择或者不选择,不选择先不给予匹配,选择,就从比$a_i$小的$b_i$中选择,排好序了,所以直接$-(j-1)$就是剩下的
最后再给其他没有给予匹配的随便给予:$f[i]*=(n-i)!$
然后根据反演式子。
或者,如果有时难以反演,就倒着求出每个g[i],用g[i+1~n]和f[i]得到g[i]
代码:
#include<bits/stdc++.h> #define reg register int #define il inline #define numb (ch^'0') using namespace std; typedef long long ll; il void rd(int &x){ char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int mod=1e9+9; const int N=2002; int n,k; int a[N],b[N]; int f[N][N],g[N]; int C[N][N]; int qm(int x,int y){ int ret=1; while(y){ if(y&1) ret=(ll)ret*x%mod; x=(ll)x*x%mod; y>>=1; } return ret; } int main(){ rd(n);rd(k); if((n+k)&1){ puts("0");return 0; } k=(n+k)>>1; for(reg i=1;i<=n;++i) rd(a[i]); for(reg j=1;j<=n;++j) rd(b[j]); sort(a+1,a+n+1);sort(b+1,b+n+1); int smal=0; f[0][0]=1; for(reg i=1;i<=n;++i){ while(smal<n&&b[smal+1]<a[i])++smal; for(reg j=0;j<=i;++j){ if(j&&smal>(j-1))f[i][j]=((ll)f[i-1][j-1]*(smal-(j-1)))%mod; f[i][j]=(f[i][j]+f[i-1][j])%mod; // cout<<" i j "<<i<<" "<<j<<" : "<<f[i][j]<<endl; } } int jie=1; for(reg j=n;j>=0;--j){ if(n-j)jie=(ll)jie*(n-j)%mod; f[n][j]=((ll)f[n][j]*jie)%mod; // cout<<" ff "<<f[n][j]<<endl; } C[0][0]=1; for(reg i=1;i<=n;++i){ C[i][0]=1; for(reg j=1;j<=n;++j){ C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } } for(reg i=n;i>=k;--i){ if(i==n){ g[i]=f[n][i]; }else{ int sum=0; for(reg j=i+1;j<=n;++j){ sum=(sum+(ll)C[j][i]*g[j]%mod)%mod; } g[i]=(ll)((ll)f[n][i]-sum+mod)%mod; } } printf("%d",g[k]); return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2019/2/18 8:32:07 */