• 动态规划:数位DP


    数位dp一般应用于:

    求出在给定区间[A,B]内,符合条件P(i)的数i的个数

    条件P(i)一般与数的大小无关,而与 数的组成 有关

    例题是一道BZOJ1833,让求出区间所有整数每个数字出现的次数

    递推出f[i][j][k]表示长度为i开头j的所有数字中k的个数

    这个东西让我想起了大模拟,高精度

     1 #include<cstdio>
     2 using namespace std;
     3 //a,b 10^12
     4 long long a,b;
     5 long long t[25];
     6 struct Data{long long a[15];}f[25][15];
     7 Data operator +(Data a,Data b)
     8 {
     9     Data t;
    10     for(int k=0;k<=9;k++)
    11         t.a[k]=a.a[k]+b.a[k];
    12     return t;
    13 }
    14 inline long long read()
    15 {
    16     long long x=0,f=1;char ch=getchar();
    17     while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    18     while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    19     return x*f;
    20 }
    21 Data cal(long long x)
    22 {
    23     Data ans;for(int i=0;i<=9;i++) ans.a[i]=0;
    24     if(x==0)
    25     {
    26         ans.a[0]=1;
    27         return ans;
    28     }
    29     int len=15;
    30     while(t[len]>x) len--;
    31     for(int i=1;i<len;i++)
    32         for(int j=1;j<=9;j++)
    33             ans=ans+f[i][j];
    34     ans.a[0]++;
    35     int cur=x/t[len];
    36     for(int i=1;i<cur;i++) ans=ans+f[len][i];
    37     x%=t[len];
    38     ans.a[cur]+=x+1;
    39     for(int i=len-1;i;i--)
    40     {
    41         cur=x/t[i];
    42         for(int j=0;j<cur;j++)
    43             ans=ans+f[i][j];
    44         x%=t[i];
    45         ans.a[cur]+=x+1;
    46     }
    47     return ans;
    48 }
    49 int main()
    50 {
    51     t[1]=1;
    52     for(int i=2;i<=15;i++) t[i]=t[i-1]*10;
    53     for(int i=0;i<=9;i++) f[1][i].a[i]=1;
    54     //初始化
    55     //递推出f[i][j][k]表示长度为i开头j的所有数字中k的个数 
    56     for(int i=2;i<=12;i++)  //数字长度 
    57         for(int x=0;x<=9;x++)
    58             for(int y=0;y<=9;y++)
    59             {
    60                 f[i][y]=f[i][y]+f[i-1][x];
    61                 f[i][y].a[y]+=t[i-1];
    62             }
    63     a=read();b=read();
    64     Data t1=cal(b),t2=cal(a-1);
    65     for(int i=0;i<=9;i++)
    66     {
    67         printf("%lld",t1.a[i]-t2.a[i]);
    68         if(i!=9) printf(" ");
    69     }
    70     return 0;
    71 }

    cal函数就是计算从0到当前数中每一个数字出现的次数,对a和b分别求然后作差就好了

    挺恶心的一种dp

  • 相关阅读:
    卸载cuda,以及N卡驱动
    ubuntu 16.04 从gcc 5.4 安装gcc 5.3.0
    Check failed: status == CUBLAS_STATUS_SUCCESS (13 vs. 0) CUBLAS_STATUS_EXECUTION_FAILED
    ubuntu16.04 caffe cuda9.1 segnet nvidia gpu安装注意的点
    ubuntu16.04安装docker
    进程管理
    Dev TextEdit 只输入数字
    dev gridcontrol添加右键菜单
    WinForm rdlc 报表自定义datatable数据源
    DevExpress GridControl使用方法总结2 属性说明
  • 原文地址:https://www.cnblogs.com/aininot260/p/9466356.html
Copyright © 2020-2023  润新知