省选不杂题乱写(2)

BZOJ 2863 愤怒的元首(DP,二项式反演)

\(n\)个点的\(\text{DAG}\)进行计数。图无需连通,\(n \leq 3000\)

我们考虑\(\text{DAG}\)的性质:在\(\text{DAG}\)上解决问题的时候,我们通常使用拓扑排序:这样相当于把图变成了一层一层,每次去掉了入度为\(0\)的点的一层。

考虑二项式反演。设\(f_{i,j}\)表示\(i\)个点,钦定了其中\(j\)个点入度为\(0\)的统计方案数,再设\(g_{i,j}\)表示\(i\)个点,其中\(j\)个点入度为\(0\)的方案数。则:

\[f_{i,j}=\sum\limits_{k=j}^{i}{k \choose j}g_{i,k} \]

由二项式反演,得:

\[g_{i,j}=\sum\limits_{k=j}^i(-1)^{k-j}{k \choose j}f_{i,k} \]

另外,\(\color{orange}{我们需要满足在}\)统计\(\color{orange}{和}\)钦定\(\color{orange}{这两步中,}\)钦定\(\color{orange}{这一步的计算是准确的。}\)

\(a_i\)表示\(i\)个点组成的\(DAG\)个数,则:

\[f_{i,j}={i \choose j}2^{j(i-j)}a_{i-j} \]

又:

\[\begin{aligned} a_n&=\sum\limits_{i=1}^{n}g_{n,i}\\ &=\sum\limits_{i=1}^n\sum\limits_{j=i}^n(-1)^{j-i}{j \choose i}f_{n,j}\\ &=\sum\limits_{i=1}^n\sum\limits_{j=i}^n(-1)^{j-i}{j \choose i}{n \choose j}2^{j(n-j)}a_{n-j}\\ &=\sum\limits_{j=1}^n\sum\limits_{i=1}^j(-1)^{j-i}{j \choose i}{n \choose j}2^{j(n-j)}a_{n-j}\\ &=\sum\limits_{j=1}^n(-1)^j{n \choose j}2^{j(n-j)}a_{n-j}\sum\limits_{i=1}^j(-1)^{i}{j \choose i}\\ &=\sum\limits_{j=1}^n(-1)^j{n \choose j}2^{j(n-j)}a_{n-j}((1-1)^j-{j \choose 0})\\ &=\sum\limits_{j=1}^n(-1)^{j-1}{n \choose j}2^{j(n-j)}a_{n-j} \end{aligned} \]

于是得到了递推式。

原来还能这么写啊(


BZOJ 4008 [HNOI2015]亚瑟王(DP,概率期望)

我的意见是,我没意见.jpg

很容易想到,计算每张卡牌\(被选择的概率\)(或者更好算的,\(1-不选择的概率\))。

比如说像第一张牌,被选择的概率为:

\(A_1=1-(1-P_1)^r\)

因为是这样的:每一轮都没有选择第\(1\)张卡,则每一轮都要考虑第\(1\)张卡能否发动这件事

也就是看看 第\(i\)张被考虑是否发动 的次数

再思考一下,发现:

  • 如果在某一轮中,卡\(i\)前面的某张卡成功发动,则卡\(i\)在该轮一定被考虑。

  • 否则,卡\(i\)一定不会被考虑。

所以前\(i-1\)张卡成功发动的次数\(j\)决定了\(i\)的被考虑次数\(r-j\)

\(f_{i,j}\)表示前\(i\)张卡里有\(j\)张被选择的概率,则有:

\[A_i=\sum\limits_{j=0}^{i-1}f_{i-1,j} \times (1-(1-p_i)^{r-j}) \]

再看看\(f\)怎么转移。

  1. 选了第\(i\)

\[f_{i,j}=f_{i-1,j-1}\times(1-(1-p_i)^{r-j+1}) \]

  1. 不选第\(i\)张:

\[f_{i,j}=f_{i-1,j}\times(1-p_i)^{r-j+1} \]

>w<


「SHOI2017」组合数问题(DP,组合意义,矩阵加速)

给定\(n\)\(p\)\(k\)\(r\),求下柿的值。

\[\left( \mathrm{C}_{nk}^{r} + \mathrm{C}_{nk}^{k + r} + \mathrm{C}_{nk}^{2k + r} + \cdots + \mathrm{C}_{nk}^{(n - 1)k + r} + \mathrm{C}_{nk}^{nk + r} + \cdots \right) \bmod p \]

\[1 \leq n \leq 10^9, 0 \leq r < k \leq 50, 2 \leq p \leq 2^{30} - 1 \]

暴力拆柿饼无果,看看组合意义。

求:从\(nk\)个元素中取出模\(k\)意义下\(r\)个元素的方案数。

\(f_{i,j}\)表示\(i\)个元素中取出模\(k\)意义下\(j\)个元素的方案数。则:

\[f_{i,j}= \left \{ \begin{array}{ll} f_{i-1,j-1}+f_{i-1,j} & (j > 0)\\ f_{i-1,0}+f_{i-1,k-1} & (j = 0)\\ \end{array} \right.\]

由于转移只涉及相邻两行,\(k\)\(r\)比较小,可以矩阵加速掉。转移矩阵\(\text{E}\)如下:

\[\begin{bmatrix} 1 & 1 & 0 & 0 &\cdots\\ 0 & 1 & 1 & 0 &\cdots\\ 0 & 0 & 1 & 1 &\cdots\\ &&\cdots\\ 1&0&\cdots&0&1\\ \end{bmatrix}\]

好像要特判\(k=1\).........

Code
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
#define MAXN 51
long long mod;
int n,k,r;
struct Mar
{
	int n,m;
	long long a[MAXN][MAXN];
	Mar() { for (int i=0;i<MAXN;i++) for (int j=0;j<MAXN;j++) a[i][j]=0; }
}O,E;
Mar operator * (const Mar &A,const Mar &B)
{
	Mar C;
	C.n=A.n; C.m=B.m;
	for (int k=1;k<=B.n;k++)
		for (int i=1;i<=C.n;i++)
			for (int j=1;j<=C.m;j++)
				C.a[i][j]=(C.a[i][j]+A.a[i][k]*B.a[k][j]%mod)%mod;
	return C;
}
inline Mar mqpow(Mar A,long long B)
{
	Mar ANS=O,base=A;
	while (B)
	{
		if (B&1) ANS=ANS*base;
		base=base*base; B>>=1;
	}
	return ANS;
}
inline long long qpow(long long A,long long B)
{
	long long ANS=1,base=A;
	while (B)
	{
		if (B&1) ANS=ANS*base%mod;
		base=base*base%mod; B>>=1;
	}
	return ANS;
}
/*
inline void Mprint(Mar A)
{
	puts("----------");
	for (int i=1;i<=A.n;i++,cout<<endl)
		for (int j=1;j<=A.m;j++)
			printf("%d ",A.a[i][j]);
	puts("----------");
}
*/

int main()
{
	scanf("%d%lld%d%d",&n,&mod,&k,&r);
	if (k==1) return printf("%lld\n",qpow(2,1ll*n*k)),0;
	E.n=E.m=k;
	for (int i=1;i<k;i++)
		E.a[i][i]=E.a[i][i+1]=1;
	E.a[k][1]=E.a[k][k]=1;
//	Mprint(E);
	O.n=O.m=k;
	for (int i=1;i<=k;i++)
		O.a[i][i]=1;
	Mar A;
	A.n=1; A.m=k; A.a[1][1]=1;
	Mar ans=A*mqpow(E,1ll*n*k);
//	Mprint(ans);
	printf("%lld\n",ans.a[1][r+1]);
	return 0;
}

[IOI2005]Riv 河流(树形背包,加维解决后效性)

泛化物品背包。对于某一个\(\color{orange}{泛化物品,在给其\ w\ 的费用时,其价值为\ h_w\ }\)

对于该题,价值应为节省的开销。节省的开销由两个变量决定:

\((1)\)该点的产树量;\((2)\)离该点最近的有伐木场的祖先的距离(为此要\(\color{orange}{特意加一维来解决后效性。}\))。

泛化物品则是子树;费用是子树使用的伐木场个数。

\(f_{x,w,z}\) 表示以x为根节点的子树,使用w个伐木场,最近祖先为z的节省开销数

那这就变成一个树形背包聊

复杂度是否为 \(O(n^2k^2)\) ..?为什么听有人说是 \(O(n^2k)\)


[HAOI2015]树上染色(树形背包)

主要的技巧是\(\color{orange}{路径贡献转化为边贡献}\)

考虑某一条边的贡献,可以由其一侧的黑白点个数来决定。边权可以扔点权上()

以泛化物品来理解:当给该边对应子树的黑点容量为 \(w\) ,白点容量为 \(siz_x-w\) 的时候,另一侧黑点容量为 \(k-w\) ,白点容量为 \(n+w-siz_x-k\) ,则有:

\[h(w)=w\times(k-w)+(siz_x-w)\times(n+w-siz_x-k) \]

\(f_{x,w}\) 表示以 \(x\) 为根节点的子树(带着 \(x\) 到父亲的边)的最大贡献。

然后就是树上背包。

要分节点 \(x\) 染成黑/白的情况分别计算。


[HAOI2008] 硬币购物()

首先计算出不限制硬币个数时,也即完全背包的答案。

这个比较不变 对吧()在多组询问中,我们最先能处理的只有这个。

我本来想求购买至多/至少 \(s\) 价值的价值的东西的付款方案数,其实做不了

其实还可以求使用了至少 \(x\) 枚第 \(i\) 种硬币。使用最多 \(d_i\) 枚硬币 = 使用任意枚硬币 - 使用至少 \(d_i+1\)枚硬币。

使用至少 \(d_i+1\) 枚硬币的方案,可以是先强制选择 \(d+1\) 枚硬币,再任意选择硬币。也即 \(f_{s-c_i\times(d_i+1)}\)

可以瞎 jb 容斥。

posted @ 2022-09-19 14:57  Akuto_urusu  阅读(38)  评论(0)    收藏  举报