zoukankan      html  css  js  c++  java
  • 【Dream Counting, 2006 Dec-数数的梦】数位dp

    题意:给定两个数,问区间[A,B]中0~9分别出现了多少次。A,B<=10^18

    题解:应该是最裸的数位dp吧。。一开始没有记忆化tle了TAT

    我们可以求出区间[0,B]的,再减去区间[0,A]的。

    用dfs实现,记录flag(填了的位是否和边界重合),zero(当前是否还在前缀0中)

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<ctime>
     6 #include<queue>
     7 using namespace std;
     8 
     9 typedef long long LL;
    10 const int N=100;
    11 int c[N][N][2][2],d[N],sum[N];
    12 LL bit[N],ret[N];
    13 
    14 LL g(int now,int x,int flag,int zero)
    15 {
    16     if(c[now][x][flag][zero]!=-1) return c[now][x][flag][zero];
    17     if(x==0) return 0;
    18     LL ans=0;
    19     if(flag)
    20     {
    21         for(int i=0;i<d[x];i++) 
    22         {
    23             ans+=g(now,x-1,0,zero & (i==0));
    24             if(i==now && !(i==0 && zero)) ans+=bit[x-1];
    25         }
    26         ans+=g(now,x-1,1,zero && (d[x]==0));
    27         if(now==d[x] && !(now==0 && zero)) ans+=ret[x-1]; 
    28     }
    29     else
    30     {
    31         for(int i=0;i<=9;i++) 
    32         {
    33             ans+=g(now,x-1,0,zero & (i==0)); 
    34             if(i==now && !(i==0 && zero)) ans+=bit[x-1];
    35         }
    36     }
    37     // printf("now %d  x %d  flag %d  zero %d  = %d
    ",now,x,flag,zero,ans);
    38     c[now][x][flag][zero]=ans;
    39     return ans;
    40 }
    41 
    42 void solve(LL x,LL tmp)
    43 {
    44     memset(d,0,sizeof(d));
    45     memset(c,-1,sizeof(c));
    46     int l=0;LL y=x;
    47     while(y)
    48     {
    49         d[++l]=(int)(y%10);
    50         y/=10;
    51     }
    52     for(int i=0;i<=18;i++) ret[i]=x%bit[i]+1;
    53     for(int i=0;i<=9;i++) sum[i]+=g(i,20,1,1)*tmp;
    54 }
    55 
    56 int main()
    57 {
    58     // freopen("a.in","r",stdin);
    59     freopen("dream.in","r",stdin);
    60     freopen("dream.out","w",stdout);
    61     LL A,B;int x;
    62     scanf("%lld%lld",&A,&B);
    63     memset(sum,0,sizeof(sum));
    64     bit[0]=1;
    65     for(int i=1;i<=18;i++) bit[i]=bit[i-1]*10;
    66     solve(A-1,-1);
    67     solve(B,1);
    68     for(int i=0;i<=9;i++) printf("%d ",sum[i]);
    69     return 0;
    70 }
  • 相关阅读:
    贪婪大陆
    色板游戏
    11/29 NOIP 模拟赛
    USACO4.4 重叠的图像 Frame Up
    CSP2020 题解
    NOIP前板子复习
    关于我
    【洛谷】【搜索+字符串】
    【洛谷】【动态规划/01背包】P2925 [USACO08DEC]干草出售Hay For Sale
    【洛谷】【二分查找】P1102 A−B数对
  • 原文地址:https://www.cnblogs.com/KonjakJuruo/p/6021767.html
Copyright © 2011-2022 走看看