前言

继续学习容斥的技巧!

题意简介

题面链接

题目大意

给出两个数组a,ba,ba,b
求有多少种对应方式使得有恰好kkk对匹配(i,j)(i,j)(i,j)满足ai>bja_i>b_jai​>bj​

数据范围

n≤2000,0≤k≤nn\le2000,0\le k\le nn≤2000,0≤k≤n

题解

部分分

这道题的暴力是指数级的,对于这样的数据范围显得非常没有意义

正解

发现暴力的瓶颈在于枚举匹配的集合,那么说明我们不能直接枚举集合
考虑减少限制,使得计算变得简单,然后再把不满足的都扔掉,那么就能做出这道题,也就是容斥
我们先将两个数组分别排序,这样的话容易发现对于aaa中的一个元素aia_iai​,满足ai>bja_i>b_jai​>bj​的bjb_jbj​是bbb的一个前缀
定义g[i]g[i]g[i]为最大的下标jjj满足bj&lt;aib_j&lt;a_ibj​<ai​
定义f[i][j]f[i][j]f[i][j]表示aaa数组的前iii个数,其中确定有jjj对匹配满足a&gt;ba&gt;ba>b(确定那么多,但不代表只有那么多),在这样的情况下这jjj对的选择方案数(这jjj对以外的数的匹配不同算同一种方案)
然后很容易贴出转移式子f[i][j+1]=f[i−1][j+1]+f[i−1][j]∗(g[i]−j)f[i][j+1]=f[i-1][j+1]+f[i-1][j]*(g[i]-j)f[i][j+1]=f[i−1][j+1]+f[i−1][j]∗(g[i]−j)
第一项代表当前这个数不匹配,第二项表示当前这个数匹配
设F[i]=f[n][i]∗(n−i)!F[i]=f[n][i]*(n-i)!F[i]=f[n][i]∗(n−i)!,那么F[i]F[i]F[i]就表示满足a&gt;ba&gt;ba>b的匹配对数大于等于jjj的对应方式数(注意,这个定义和上面的不同,乘一个阶乘后就所有数都固定了)
定义Ans[i]Ans[i]Ans[i]表示满足a&gt;ba&gt;ba>b的匹配对数等于jjj的对应方式数
容易发现Ans[k]Ans[k]Ans[k]即我们所要的答案
我们发现这样一个显然的式子F[k]=∑i=kn(ik)Ans[i]F[k]=\sum_{i=k}^n\binom{i}{k}Ans[i]F[k]=i=k∑n​(ki​)Ans[i]
注:(ij)=C(i,j)\binom{i}{j}=C(i,j)(ji​)=C(i,j)即组合数
二项式反演即可得Ans[k]=∑i=kn(−1)i−k(ik)F[i]Ans[k]=\sum_{i=k}^n(-1)^{i-k}\binom{i}{k}F[i]Ans[k]=i=k∑n​(−1)i−k(ki​)F[i]
那么什么是二项式反演呢?请看下一节
我们先把这题讲完,假设你推出了这个,那么就可以直接算答案了
前面dpdpdp的复杂度是Θ(n2)\Theta(n^2)Θ(n2)的,后面的答案计算由于只要算一个所以是Θ(n)\Theta(n)Θ(n)的
综上,总复杂度Θ(n2)\Theta(n^2)Θ(n2)

二项式反演

二项式反演的经典形式为fn=∑i=0n(−1)i(ni)gi⇔gn=∑i=0n(−1)i(ni)fif_n=\sum_{i=0}^n(-1)^i\binom{n}{i}g_i\Leftrightarrow g_n=\sum_{i=0}^n(-1)^i\binom{n}{i}f_ifn​=i=0∑n​(−1)i(in​)gi​⇔gn​=i=0∑n​(−1)i(in​)fi​
这篇博客用到的式子是另一个经典模型
fi=∑j=0i(n−jn−i)gj⇔gi=∑j=0i(−1)i−j(n−jn−i)fjf_i=\sum_{j=0}^i\binom{n-j}{n-i}g_j\Leftrightarrow g_i=\sum_{j=0}^i(-1)^{i-j}\binom{n-j}{n-i}f_jfi​=j=0∑i​(n−in−j​)gj​⇔gi​=j=0∑i​(−1)i−j(n−in−j​)fj​
应用的时候其实是进行了数组翻转和特殊值代换产生的
要问证明?请看我的另一篇总结博客

代码

东西讲完了,就可以安心写出前面的那一题了,贴上ac代码

#include<cstdio>
#include<cctype>
#include<algorithm>
namespace fast_IO
{const int IN_LEN=10000000,OUT_LEN=10000000;char ibuf[IN_LEN],obuf[OUT_LEN],*ih=ibuf+IN_LEN,*oh=obuf,*lastin=ibuf+IN_LEN,*lastout=obuf+OUT_LEN-1;inline char getchar_(){return (ih==lastin)&&(lastin=(ih=ibuf)+fread(ibuf,1,IN_LEN,stdin),ih==lastin)?EOF:*ih++;}inline void putchar_(const char x){if(oh==lastout)fwrite(obuf,1,oh-obuf,stdout),oh=obuf;*oh++=x;}inline void flush(){fwrite(obuf,1,oh-obuf,stdout);}
}
using namespace fast_IO;
#define getchar() getchar_()
#define putchar(x) putchar_((x))
#define rg register
typedef long long LL;
template <typename T> inline T max(const T a,const T b){return a>b?a:b;}
template <typename T> inline T min(const T a,const T b){return a<b?a:b;}
template <typename T> inline void mind(T&a,const T b){a=a<b?a:b;}
template <typename T> inline void maxd(T&a,const T b){a=a>b?a:b;}
template <typename T> inline T abs(const T a){return a>0?a:-a;}
template <typename T> inline void swap(T&a,T&b){T c=a;a=b;b=c;}
template <typename T> inline T gcd(const T a,const T b){if(!b)return a;return gcd(b,a%b);}
template <typename T> inline T lcm(const T a,const T b){return a/gcd(a,b)*b;}
template <typename T> inline T square(const T x){return x*x;};
template <typename T> inline void read(T&x)
{char cu=getchar();x=0;bool fla=0;while(!isdigit(cu)){if(cu=='-')fla=1;cu=getchar();}while(isdigit(cu))x=x*10+cu-'0',cu=getchar();if(fla)x=-x;
}
template <typename T> inline void printe(const T x)
{if(x>=10)printe(x/10);putchar(x%10+'0');
}
template <typename T> inline void print(const T x)
{if(x<0)putchar('-'),printe(-x);else printe(x);
}
const LL mod=1000000009;
inline void md(LL&x){if(x>=mod)x-=mod;}
int n,k;
int a[2001],b[2001],g[2001];
inline LL pow(LL x,LL y)
{LL res=1;for(;y;y>>=1,x=x*x%mod)if(y&1)res=res*x%mod;return res;
}
LL fac[2001],inv[2001];
inline LL C(const LL x,const LL y)
{return fac[x]*inv[y]%mod*inv[x-y]%mod;}
LL f[2001],ans;
int main()
{read(n),read(k);if((n&1)!=(k&1)){print(0);return flush(),0;}k=(n-k)/2+k;for(rg int i=1;i<=n;i++)read(a[i]);for(rg int i=1;i<=n;i++)read(b[i]);std::sort(a+1,a+n+1);std::sort(b+1,b+n+1);for(rg int i=1,j=0;i<=n;i++){while(j<n&&b[j+1]<a[i])j++;g[i]=j;}fac[0]=1;for(rg int i=1;i<=n;i++)fac[i]=fac[i-1]*i%mod;inv[n]=pow(fac[n],mod-2);for(rg int i=n;i>=1;i--)inv[i-1]=inv[i]*i%mod;f[0]=1;for(rg int i=1;i<=n;i++)for(rg int j=n-1;j>=0;j--)md(f[j+1]+=f[j]*(g[i]-j)%mod);for(rg int i=k,j=1;i<=n;i++,j^=1){if(j)ans+=f[i]*C(i,k)%mod*fac[n-i]%mod;else ans-=f[i]*C(i,k)%mod*fac[n-i]%mod;}ans%=mod,ans+=mod,ans%=mod;print(ans);return flush(),0;
}

总结

二项式反演还是挺有效的,也很好用,继续学习!

二项式反演[bzoj3622]已经没有什么好害怕的了相关推荐

  1. 二项式反演(学习笔记)

    q w q qwq qwq机房最后一个学二项式反演的人 众所周知 二项式反演可以表示成 f n = ∑ i = 0 n ( − 1 ) i × C n i × g i ⟺ g n = ∑ i = 0 ...

  2. 二项式反演(非详细)

    引入 二项式反演又名广义容斥定理 二项式反演可以表示成: f[n]=∑i=0n(−1)iCnigi⟺gn=∑i=0n(−1)iCnif[i]f[n]=\sum_{i=0}^n(-1)^iC_{n}^{ ...

  3. 二项式反演(广义容斥定理)学习笔记

    背景: 二项式反演又名广义容斥定理. 下次再看题解时要注意了. 解锁新姿势. 说白了就是之前会的姿势太少了. 正题: 说白了就是有这样两条恒等的式子: f n = ∑ i = 0 n ( − 1 ) ...

  4. ACM数论之旅17---反演定理 第一回 二项式反演(神说要有光 于是就有了光(´・ω・`))...

    终于讲到反演定理了,反演定理这种东西记一下公式就好了,反正我是证明不出来的~(-o ̄▽ ̄)-o 首先,著名的反演公式 我先简单的写一下o( ̄ヘ ̄*o) 比如下面这个公式 f(n) = g(1) + g ...

  5. 集合计数 二项式反演_对计数数据使用负二项式

    集合计数 二项式反演 The Negative Binomial distribution is a discrete probability distribution that you should ...

  6. [2021.1.27多校省选模拟10]染色(min-max容斥/二项式反演)

    [2021.1.27多校省选模拟10]染色 突然发现我对概率期望的理解不是很好... 部分分1:可以直接进行状压dp,然后按照题意模拟即可. 部分分2:首先可以发现这个问题是min_max容斥形式,然 ...

  7. P6295 有标号 DAG 计数(多项式指数函数对数函数/二项式反演/动态规划/生成函数)

    P6295 有标号 DAG 计数 https://www.luogu.com.cn/problem/P6295 求解n个点的有标号弱联通DAG个数 首先根据exp的组合意义,我们考虑指数型生成函数,那 ...

  8. 【UOJ574】多线程计算【二元二项式反演】【定积分】【矩阵】【NTT 卷积】

    题意:有 n×mn\times mn×m 的网格,每个结点在 [0,1)[0,1)[0,1) 内的一个随机时刻被点亮.有 hhh 个数对 xi,yix_i,y_ixi​,yi​,对于一个瞬间状态,如果 ...

  9. 【LOJ6072】苹果树【折半搜索】【矩阵树定理】【二项式反演】

    题意:有好坏两种点共 nnn 个,每个好点有权值,把这 nnn 个点连成一棵树,一个好点为有用的当且仅当它至少与一个好点相邻,求所有有用的点的权值和不超过 limlimlim 的方案数. n≤40n\ ...

最新文章

  1. 敏捷开发一千零一问系列之四:优先级排错怎么办?
  2. 用createinstallmedia创建可恢复的OSX安装DMG
  3. Python课堂:判定IP地址合法性的三种方法
  4. 新装WINDOWS XP系统 必须安装的十大高危漏洞补丁
  5. Javascript获取屏幕与页面尺寸
  6. CPython对象模型:整型
  7. Hibernate Tomcat JNDI DataSource示例教程
  8. arcgis 删除图形重复折点_【干货】ArcGIS中画环状图斑、挑子区及消除图斑重复区域...
  9. QT出现 Cannot create children for a parent that is in a different thread 的解决方法:
  10. 框架学习 Spring之概念
  11. Mysql备份策略-完成备份+增量备份shell
  12. 不能忽视的情绪 -- 喜怒哀惧,也不过度关注
  13. excel熵值法计算权重_由搜索权重排序引入的思考
  14. 小程序之模版消息通知
  15. PyCharm大学生教育账户激活
  16. EMC与电阻、电容和电感的关系
  17. Excel条件格式使用小总结
  18. 哈希表 matlab实现,MATLAB中的哈希表
  19. 清北学堂 2017-10-05
  20. 【二分】C. Keshi Is Throwing a Party

热门文章

  1. SpringMVC的请求-获得请求参数-获得数组类型参数
  2. 接口中也可以有方法了
  3. 常用的函数式接口_Predicate接口练习_集合信息筛选
  4. Hive的基本操作-创建外部表
  5. 手动使用cglib代理(了解)
  6. 日期和时间 - Java处理日期和时间
  7. 算法和时间复杂度概念(一级)
  8. 闭包案例产生多个相同的随机数 沙箱
  9. JDK1.8并发包中的类
  10. javascript等待异步线程完成_作为前端你了解JavaScript运行机制吗?