zoukankan      html  css  js  c++  java
  • 洛谷 P2602 [ZJOI2010]数字计数(数位DP)

    题目链接:https://www.luogu.com.cn/problem/P2602

    这道题大意是求某区间内数字0-9出现的次数。

    分别统计区间内存在1个1,2个1,3个1……的数的个数,存在1个2,2个2,……,1个9,2个9,……的数的个数,然后求累加:累加的是次数*个数。

    注意前导0和DFS最后的边界的处理。

    num:哪一个数码        cnt:次数      now:已出现的次数

    dp第一维记录pos,第二维记录now,第三维记录cnt,里面存ans。

    AC代码:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 typedef long long ll;
     7 ll dp[20][20][20],ans[50];
     8 int a[50];
     9 ll DFS(int pos,int now,int limit,int lead,int cnt,int num){
    10     if(pos==0) return now==cnt;//注意边界处理 
    11     if(!limit&&!lead&&dp[pos][now][cnt]!=-1) return dp[pos][now][cnt];
    12     int up=limit?a[pos]:9;
    13     ll ans=0;
    14     for(int i=0;i<=up;i++){
    15         if(lead&&i==0) ans+=DFS(pos-1,now,limit&&i==a[pos],1,cnt,num);
    16         else ans+=DFS(pos-1,now+(i==num),limit&&i==a[pos],0,cnt,num);
    17     }
    18     if(!lead&&!limit) dp[pos][now][cnt]=ans;
    19     return ans;
    20 }
    21 void solve(ll x,int flag){
    22     int len=0;
    23     memset(dp,-1,sizeof(dp));
    24     while(x){
    25         a[++len]=x%10;
    26         x/=10;
    27     }
    28     for(int i=0;i<=9;i++){
    29         for(int j=1;j<=len;j++){//枚举出现的次数 
    30             if(flag) ans[i]+=j*DFS(len,0,1,1,j,i);
    31             else ans[i]-=j*DFS(len,0,1,1,j,i);
    32         }
    33     }
    34 }
    35 int main(){
    36     ll n,m;
    37     scanf("%lld%lld",&n,&m);
    38     solve(n-1,0); solve(m,1);
    39     for(int i=0;i<=9;i++) printf("%lld ",ans[i]);
    40     return 0;
    41 }
    AC代码
  • 相关阅读:
    centos 编程环境
    git 安装 使用
    nodejs 笔记
    微信开发
    composer 使用笔记
    一:安装centos 7最小编程环境 xfce桌面
    二: 安装centos服务环境软件mysql httpd php
    我的通用程序规范及说明
    常用js代码集
    三 , lnmp 一键包安装使用
  • 原文地址:https://www.cnblogs.com/New-ljx/p/12450518.html
Copyright © 2011-2022 走看看