首页 > 其他分享 >动态规划进阶

动态规划进阶

时间:2023-12-17 21:57:48浏览次数:34  
标签:进阶 int sum len long query 动态 规划 sim

数位DP

常见的模板:询问 \(l\sim r\) 中有多少个满足给定条件的数,\(1\le l\le r\le 10^{18}\)。

这种问题,数位DP可以做到 \(O(\log v)\) 级别,其中 \(v\) 是 \(l,r\) 的值域。

思路

直接枚举会枚举大量不可能满足条件的数,可以从数位入手。

数位DP的算法流程如下:

  1. 几个定义:

    • \(len(x)\) 表示 \(x\) 的位数。

    • \(d(x,i)\) 表示 \(x\) 的第 \(i\) 位上的数字。

  2. 预处理,设 \(f_{i,j,...}\) 表示位数位 \(i\),最高位为 \(j\),满足给定条件的数的个数。

  3. 统计答案,令 \(query(x)\) 表示 \(1\sim x-1\) 中满足给定条件的数的个数,答案为 \(query(r+1)-query(l)\)。

    1. 统计位数为 \(1\sim len(x)-1\) 的数。

    2. 统计位数为 \({len}(x)\) 的数。

      • 统计第 \(1\sim len(x)-1\) 位都与 \(x\) 相同,且第 \(len(x)\) 位不超过 \(d(x,len(x))\) 的数。注意,如果题目考虑前导零,则不进行该步骤。

      • 统计第 \(1\sim i\) 位都与 \(x\) 相同,且第 \(i\) 位不超过 \(d(x,i)\) 的数。

例题

luogu.CF1036C/CF1036C

设 \(f_{i,j,k}\) 表示所有位数为 \(i\),最高位为 \(j\),有 \(k\) 个数位上的数字为 \(1\sim 9\) 的数字个数。

转移:

\(f_{i,j,k}=\begin{cases}\displaystyle\sum_{c=0}^9 f_{i-1,c,k}\ (j=0)\\ \displaystyle\sum_{c=0}^9 f_{i-1,c,k-1}\ (j\ne 0,k\ne 0)\end{cases}\)

初始值:\(f_{1,0,0}=1,f_{1,1\sim 9,1}=1\)

定义 \(len(x)\) 表示 \(x\) 的位数,\(d(x,i)\) 表示 \(x\) 的第 \(i\) 为上的数字,\(query(x)\) 表示 \(1\sim x-1\) 中有多少个“好数”,答案为 \(query(r+1)-query(l)\)。

\(query(x)\) 由两部分组成:

  1. 位数为 \(1\sim len(x)-1\) 的“好数”。

    总数为 \(\displaystyle\sum_{i=1}^{len(x)-1}\sum_{j=1}^9\sum_{k=1}^3 f_{i,j,k}\)

  2. 位数为 \({len}(x)\) 的“好数”,因为要去掉前导零,把最高位单独考虑:

    • 考虑第 \(1\sim len(x)-1\) 位都与 \(x\) 相同,且第 \(len(x)\) 位不超过 \(d(x,len(x))\) 的“好数”,总数为 \(\displaystyle\sum_{i=1}^{d(x,len(x))-1}\sum_{j=0}^3 f_{len(x),i,j}\)

    • 考虑第 \(1\sim i\) 位都与 \(x\) 相同,且第 \(i\) 位不超过 \(d(x,i)\),总数为 \(\displaystyle\sum_{i=1}^{len(x)-1}\sum_{j=0}^{d(x,i)-1}\sum_{k=0}^{3-cnt(i)}f_{i,j,k}\),其中 \(cnt(i)\) 表示 \(x\) 的 \(i\sim len(x)-1\) 位中有多少位为 \(1\sim 9\)。

#include <bits/stdc++.h>
using namespace std;
int t, d[25];
long long l, r, f[25][25][25];
long long query(long long x) {
    int len = 0;
	long long ret = 0;

    while (x)
        d[++len] = x % 10, x /= 10;

    for (int i = 1; i < len; i++)
        for (int j = 1; j <= 9; j++)
            for (int k = 0; k <= 3; k++)
                ret += f[i][j][k];

    for (int i = 1; i < d[len]; i++)
        for (int j = 0; j <= 3; j++)
            ret += f[len][i][j];

    for (int i = len - 1, cnt = 0; i >= 1; i--) {
        if (d[i])
            cnt++;

        for (int j = 0; j < d[i]; j++)
            for (int k = 0; k <= 3 - cnt; k++)
                ret += f[i][j][k];
    }

    return ret;
}
int main() {
    cin >> t;
    f[1][0][0] = 1;

    for (int i = 1; i <= 9; i++)
        f[1][i][1] = 1;

    for (int i = 2; i <= 19; i++) {
        for (int j = 0; j <= 9; j++) {
            for (int k = 0; k <= 3; k++) {
                for (int c = 0; c <= 9; c++) {
                    if (!j)
                        f[i][j][k] += f[i - 1][c][k];
                    else if (k)
                        f[i][j][k] += f[i - 1][c][k - 1];
                }
            }
        }
    }

    while (t--) {
        cin >> l >> r;
        cout << query(r + 1) - query(l) << '\n';
    }

    return 0;
}

标签:进阶,int,sum,len,long,query,动态,规划,sim
From: https://www.cnblogs.com/wangxuzhou-blog/p/advanced-dynamic-programming.html

相关文章

  • js动态加载
    <scripttype="text/javascript">//动态加载js(顺序执行js)functionloadScript(url,callback){varscript=document.createElement("script")script.type="text/javascript";if(script.readyState){//IE......
  • 动态绘制svg
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content="width=......
  • 跨平台应用开发进阶(三十五) :Android权限列表permission说明
    一、前言uni-app开发完APP后,上架到应用市场,审核时会对APP内部设置的权限进行核准,并给出相应的理由。如项目中有以下权限设置:"android":{"permissions":["<uses-featureandroid:name=\"android.hardware.camera\"/>","<uses-featurea......
  • 2023ISCTF的fry题解及进阶格式化利用
    这题是一个比较好的进阶格式化利用。就是有点繁琐。先惯例checksec一下心脏骤停hhh。没事先分析一下Main函数int__cdeclmain(intargc,constchar**argv,constchar**envp){init(argc,argv,envp);puts("WelcometoISCTF~~~~~~~~~~~~~~~~");puts("Doyouwantto......
  • 非动态数组版本下的筛选
    问题:一对多查找(筛选)的结果需要横向排列,但是表格暂时不支持动态数组。右拉下拉公式解决:{=IFERROR(INDEX(FILTER($E:$E,$D:$D=$G2),COLUMN(A1)),"")}公式中的Filter部分筛选出满总D列中等产于G2对应E列的内容,其结果是多个单元格组成的数组。使用Index提取数组中的内容,第......
  • VUE框架指令语法与v-bind实现标签属性内部动态------VUE框架
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>Document</title>......
  • Threejs利用着色器编写动态飞线特效
    一、导语动态飞线特效是可视化数据地图中常见的需求之一,鼠标点击的区块作为终点,从其他区块飞线至点击区块,附带颜色变换或者结合粒子动画二、分析利用创建3点来构成贝塞尔曲线,形成线段利用着色器材质来按照线段以及时间点变化来变化线段的颜色形成动画三、上基础代码//贝塞尔曲线......
  • 零基础学习信奥如何进行科学规划
    我自己与信奥、与编程有着很深的缘分,无论是从我家孩子读书时的竞赛经历(曾经的信奥选手)还是我曾经的工作背景(之前一直在教育系统从事信息学工作),到现在自己在一线执教,管理教育教学团队,总结出一些信奥学习的基本规律。 #1信奥学习进阶路线 从零基础到高水平选手的学习历程,会经过......
  • 进阶两数交换的方法论
    今天我们来看一个简单的问题,大家对交换两个数字有多少想法呢,先看看这个。以下我们全都以1,2,为例。#include<stdio.h>voidswap(inta,intb){ intt; t=a; a=b; b=t;}intmain(){ inta=1,b=2; swap(a,b); printf("a=%db=%d\n",a,b); return0;}请问这个代码会输出......
  • 免杀-绕过静态动态查杀
    前言在我们后渗透时很多时候需要使用到一些敏感的工具,而这些工具大多都被360等杀软厂商标记。导致我们传入的工具无法执行或执行时被拦截。接下来以测试工具mimitakz为例演示如何绕过这些杀软拦截,躲避查杀等。以下为具体开发细节,程序执行时杀软拦截360静态查杀何为"静态查......