我是靠谱客的博主 勤劳小兔子,这篇文章主要介绍二项式反演(广义容斥定理)学习笔记背景:正题:例题 1 1 1(恰好与至多的转换):例题 2 2 2(恰好与至少的转换):,现在分享给大家,希望可以做个参考。

背景:

二项式反演又名广义容斥定理。
下次再看题解时要注意了。
解锁新姿势。
说白了就是之前会的姿势太少了。

正题:

说白了就是有这样两条恒等的式子:
f n = ∑ i = 0 n ( − 1 ) i C n i g i ⟺ g n = ∑ i = 0 n ( − 1 ) i C n i f i f_n=sum_{i=0}^{n}(-1)^iC_{n}^{i}g_i⟺g_n=sum_{i=0}^{n}(-1)^iC_{n}^{i}f_i fn​=i=0∑n​(−1)iCni​gi​⟺gn​=i=0∑n​(−1)iCni​fi​

仔细思考一下,发现有:
f n = ∑ i = 0 n C n i g i ⟺ g n = ∑ i = 0 n ( − 1 ) n − i C n i f i f_n=sum_{i=0}^{n}C_{n}^{i}g_i⟺g_n=sum_{i=0}^{n}(-1)^{n-i}C_{n}^{i}f_i fn​=i=0∑n​Cni​gi​⟺gn​=i=0∑n​(−1)n−iCni​fi​
证明:
感性一下就是一个容斥问题。
具体可见:http://blog.miskcoo.com/2015/12/inversion-magic-binomial-inversion 。

例题 1 1 1(恰好与至多的转换):

hdu P1465 text{hdu P1465} hdu P1465:最不容易系列之一
que text{que} que:
n n n个数重新排序,求每一个数都不在原位置的方案数。

sol text{sol} sol:
这不就是一个错排问题吗? d 1 = 0 , d 2 = 1 , d n = ( n − 1 ) ( d n − 1 + d n − 2 ) d_1=0,d_2=1,d_n=(n-1)(d_{n-1}+d_{n-2}) d1​=0,d2​=1,dn​=(n−1)(dn−1​+dn−2​)。
如果用二项式反演呢?
设 f i f_i fi​表示至多有 i i i个错开的方案数,有 f i = i ! f_i=i! fi​=i!;
设 g i g_i gi​表示恰好有 i i i个错开的方案数。
有:
f n = ∑ i = 0 n C n i g i f_n=sum_{i=0}^{n}C_{n}^{i}g_i fn​=i=0∑n​Cni​gi​

( i i i枚举当前有几个错位)
反演一下,有:
g n = ∑ i = 0 n ( − 1 ) n − i C n i f i = ∑ i = 0 n ( − 1 ) n − i C n i i ! g_n=sum_{i=0}^{n}(-1)^{n-i}C_{n}^{i}f_i=sum_{i=0}^{n}(-1)^{n-i}C_{n}^{i}i! gn​=i=0∑n​(−1)n−iCni​fi​=i=0∑n​(−1)n−iCni​i!

code text{code} code:

就不打了吧。

例题 2 2 2(恰好与至少的转换):

luogu P4859 text{luogu P4859} luogu P4859 已经没有什么好害怕的了
que text{que} que:
输入两个序列 A , B A,B A,B,保证两序列元素两两互不相同。这两个序列两两匹配,若当前配对的结果 A A A比 B B B大的组数 − B -B −B比 A A A大的组数 = k =k =k,则方案加 1 1 1,问最后的方案。
sol text{sol} sol:
首先肯定是先对 A , B A,B A,B排序。
A A A比 B B B大的组数设为 x x x, B B B比 A A A大的组数设为 y y y,那么有 x + y = n , x − y = k x+y=n,x-y=k x+y=n,x−y=k,最后 x = n + k 2 x=frac{n+k}{2} x=2n+k​。我们记 k ′ = x = n + k 2 k'=x=frac{n+k}{2} k′=x=2n+k​。
容易发现,若 n + k n+k n+k为奇数,则无解。

设 d p i , j dp_{i,j} dpi,j​表示前 i i i个 A A A中,选了至少 j j j组 a > b a>b a>b的方案数。
l a s t i last_i lasti​表示 B l a s t i B_{last_i} Blasti​​恰好小于 A i A_i Ai​,且 B l a s t i + 1 B_{last_i+1} Blasti​+1​恰好大于 A i A_i Ai​。
则有:
d p i , j = d p i − 1 , j + ( l a s t i − j + 1 ) d p i − 1 , j − 1 dp_{i,j}=dp_{i-1,j}+(last_i-j+1)dp_{i-1,j-1} dpi,j​=dpi−1,j​+(lasti​−j+1)dpi−1,j−1​
因为选了 j j j个后剩下的数可以随意排列,因此最后的结果应该乘上 ( n − j ) ! (n-j)! (n−j)!。
设 f i f_i fi​表示至少有 i i i个大于的方案数,有 f i = ( n − i ) ! d p n , i f_i=(n-i)!dp_{n,i} fi​=(n−i)!dpn,i​;
设 g i g_i gi​表示恰好有 i i i个大于的方案数。
因此有:
f k ′ = ∑ i = k ′ n C i k ′ g i f_{k'}=sum_{i=k'}^{n}C_{i}^{k'}g_i fk′​=i=k′∑n​Cik′​gi​

( i i i枚举当前有几个大于的)
反演一下,有:
g k ′ = ∑ i = k ′ n ( − 1 ) i − k ′ C i k ′ f i g_{k'}=sum_{i=k'}^{n}(-1)^{i-k'}C_{i}^{k'}f_i gk′​=i=k′∑n​(−1)i−k′Cik′​fi​

code text{code} code:

#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define mod 1000000009
using namespace std;
int a[2010],b[2010],last[2010],fac[2010],inv[2010],dp[2010][2010],f[2010];
int n,k;
int ans=0;
void init(int n)
{
fac[0]=fac[1]=1;
inv[0]=inv[1]=1;
for(int i=2;i<=n;i++)
{
fac[i]=(LL)fac[i-1]*i%mod;
inv[i]=((LL)mod-mod/i)*inv[mod%i]%mod;
}
for(int i=2;i<=n;i++)
inv[i]=(LL)inv[i-1]*inv[i]%mod;
}
int C(int n,int m)
{
return (LL)fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int main()
{
scanf("%d %d",&n,&k);
init(n);
if((n+k)&1)
{
printf("0");
return 0;
}
k=(n+k)>>1;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+n+1);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
sort(b+1,b+n+1);
int now=0;
for(int i=1;i<=n;i++)
{
while(now<n&&b[now+1]<a[i]) now++;
last[i]=now;
}
dp[0][0]=1;
for(int i=1;i<=n;i++)
{
dp[i][0]=dp[i-1][0];
for(int j=1;j<=i;j++)
dp[i][j]=((LL)dp[i-1][j]+((LL)max(last[i]-j+1,0))*dp[i-1][j-1]%mod)%mod;
}
for(int i=1;i<=n;i++)
f[i]=(LL)fac[n-i]*dp[n][i]%mod;
for(int i=1;i<=n;i++)
ans=(ans+((((i-k)&1)?-1ll:1ll)*C(i,k)*f[i]%mod+mod)%mod)%mod;
printf("%d",ans);
}

最后

以上就是勤劳小兔子最近收集整理的关于二项式反演(广义容斥定理)学习笔记背景:正题:例题 1 1 1(恰好与至多的转换):例题 2 2 2(恰好与至少的转换):的全部内容,更多相关二项式反演(广义容斥定理)学习笔记背景:正题:例题 内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(249)

评论列表共有 0 条评论

立即
投稿
返回
顶部