0、目录
线性dp、区间dp、树形dp、数位dp、概率dp、状压dp、插头dp、优化
1、线性dp
2、区间dp
2.1、一类区间配对问题
bool ok(int l,int r){
}
LL dfs(int l,int r){
if(l==r) ;
if(l==r-1){
}
if(dp[l][r]>=0) return dp[l][r];
LL& res=dp[l][r]=0;
if(ok(l,r)) res=max(res,dfs(l+1,r-1)+value);
for(int i=l;i<r;i++){
res=max(res,dfs(l,i)+dfs(i+1,r));
}
return res;
}
3、树形dp
4、数位dp
4.1、记忆化搜索模板
int arr[maxn],tot;
///type根据dp具体维数调整
int dp[maxn][type];
///ismax标记表示前驱是否是边界值
///ser标记前驱是否是前导零
LL dfs(int len,int type, bool ismax,bool iszer) {
if (len == 0) {
///递归边界,这说明前驱都合法了
return 1LL;
}
if (!ismax&&dp[len][type]>=0) return dp[len][type];
LL res = 0;
int ed = ismax ? arr[len] : 9;
///这里插入递推公式
for (int i = 0; i <= ed; i++) {
if(i==0&&iszer){
///处理前导零
}else{
res += dfs(len - 1, type, ismax&&i == ed,iszer&&i==0);
}
}
return ismax ? res : dp[len][type] = res;
}
LL solve(LL x) {
tot = 0;
while (x) { arr[++tot] = x % 10; x /= 10; }
return dfs(tot, type, true,true);
}
void init() {
memset(dp,-1);
}
5、概率dp
6、状压dp
7、插头dp
7.1、简单的插头dp模板
8、优化
8.1、矩阵快速幂:
struct Matrix {
LL mat[maxn][maxn];
Matrix() { memset(mat, 0, sizeof(mat)); }
friend Matrix operator *(const Matrix& A, const Matrix& B);
friend Matrix operator +(const Matrix &A,const Matrix &B);
friend Matrix pow(Matrix A, int n);
};
Matrix I;
Matrix operator +(const Matrix& A, const Matrix& B) {
Matrix ret;
for (int i = 0; i < maxn; i++) {
for (int j = 0; j < maxn; j++) {
ret.mat[i][j] = (A.mat[i][j] + B.mat[i][j])%mod;
}
}
return ret;
}
Matrix operator *(const Matrix& A, const Matrix& B) {
Matrix ret;
for (int i = 0; i < maxn; i++) {
for (int j = 0; j < maxn; j++) {
for (int k = 0; k < maxn; k++) {
ret.mat[i][j] = (ret.mat[i][j]+A.mat[i][k] * B.mat[k][j]) % mod;
}
}
}
return ret;
}
Matrix pow(Matrix A, int n) {
Matrix ret=I;
while (n) {
if (n & 1) ret = ret*A;
A = A*A;
n /= 2;
}
return ret;
}
void init(){
for(int i=0;i<maxn;i++) I.mat[i][i]=1;
}