背景:
二项式反演又名广义容斥定理。
下次再看题解时要注意了。
解锁新姿势。
说白了就是之前会的姿势太少了。
正题:
说白了就是有这样两条恒等的式子:
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)iCnigi⟺gn=i=0∑n(−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=0∑nCnigi⟺gn=i=0∑n(−1)n−iCnifi
证明:
感性一下就是一个容斥问题。
具体可见: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∑nCnigi
(
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−iCnifi=i=0∑n(−1)n−iCnii!
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′∑nCik′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(恰好与至少的转换):的全部内容,更多相关二项式反演(广义容斥定理)学习笔记背景:正题:例题 内容请搜索靠谱客的其他文章。
发表评论 取消回复