数位DP、概率DP学习笔记

这篇博文主要记录一下学习DP过程中的一些总结(和板子
Ongoing

数位DP

oi-wiki页面
数位DP的格式相对固定,这里放一些做过的题目的代码

上海C题

博客链接
题目链接
要求 ∑ log ⁡ 2 ( i + j ) + 1 \sum \log_2(i+j)+1 ∑log2​(i+j)+1

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int t, X, Y;
const int maxn = 32;
const ll mod = 1e9 + 7;
int xx[maxn], yy[maxn];
int lx, ly;
ll dp[maxn][2][2];

ll solve(int p, bool x, bool y)
{
	if (p == -1)
		return 1ll;
	if (dp[p][x][y] != -1)
		return dp[p][x][y];
	int xlim = x ? 1 : xx[p];
	int ylim = y ? 1 : yy[p];
	ll ans = 0;
	for (int i = 0; i <= xlim; ++i)
	{
		for (int j = 0; j <= ylim; ++j)
		{
			if (i & j)
				continue;
			ans += solve(p - 1, x | (i < xlim), y | (j < ylim));
			ans %= mod;
		}
	}
	dp[p][x][y] = ans;
	return ans;
}

int i2v(int n, int *v)
{
	int i = -1;
	for (; n; n >>= 1)
	{
		i++;
		v[i] = n & 1;
	}
	return i;
}

int main()
{
	// freopen("cin", "r", stdin);
	for (scanf("%d", &t); t--;)
	{
		memset(dp, -1, sizeof(dp));
		memset(xx, 0, sizeof(xx));
		memset(yy, 0, sizeof(yy));
		scanf("%d%d", &X, &Y);
		lx = i2v(X, xx);
		ly = i2v(Y, yy);
		ll ans = 0;
		for (int i = 0; i <= lx; ++i)
			ans = (ans + solve(i - 1, i < lx, i <= ly) * (i + 1)) % mod;
		for (int j = 0; j <= ly; ++j)
			ans = (ans + solve(j - 1, j <= lx, j < ly) * (j + 1)) % mod;
		printf("%lld\n", ans);
	}
	return 0;
}

概率DP

oi-wiki页面
概率DP与传统DP相似度很高,旨在利用选择的无后效性进行状态转移,
主要难度在于如何把递推式推出来
通常用于求期望、求概率(转移的过程中需要用到概率的线性性质,需要些概率论直觉)
目前还没有补过这方面的题,不过个人觉得oi-wiki上的抓老鼠、找bug属于比较典型的题目了
oi-wiki例题「换教室」还没看明白:(

上一篇:luogu P2257 YY的GCD


下一篇:YY/T 0664—2020《医疗器械软件 软件生存周期过程》 相关