我是靠谱客的博主 勤劳小兔子,这篇文章主要介绍二项式反演(广义容斥定理)学习笔记背景:正题:例题 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=0n(1)iCnigign=i=0n(1)iCnifi

仔细思考一下,发现有:
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=0nCnigign=i=0n(1)niCnifi
证明:
感性一下就是一个容斥问题。
具体可见: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=(n1)(dn1+dn2)
如果用二项式反演呢?
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=0nCnigi

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=0n(1)niCnifi=i=0n(1)niCnii!

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,xy=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=dpi1,j+(lastij+1)dpi1,j1
因为选了 j j j个后剩下的数可以随意排列,因此最后的结果应该乘上 ( n − j ) ! (n-j)! (nj)!
f i f_i fi表示至少 i i i个大于的方案数,有 f i = ( n − i ) ! d p n , i f_i=(n-i)!dp_{n,i} fi=(ni)!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=knCikgi

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=kn(1)ikCikfi

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(恰好与至少的转换):的全部内容,更多相关二项式反演(广义容斥定理)学习笔记背景:正题:例题 内容请搜索靠谱客的其他文章。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部