码迷,mamicode.com
首页 > 其他好文 > 详细

51Nod 1042 数字0-9的数量(数位DP)

时间:2019-03-12 21:16:44      阅读:220      评论:0      收藏:0      [点我收藏+]

标签:题解   while   double   div   fun   tmp   ems   ++   span   

题意:

求[l,r]中数字0-9分别出现的次数,11算两次1

思路:

数位dp题解好难写,直接贴代码吧

dp[i]表示[0, 10^i-1]中出现j的次数(按i位补全前导0,显然0-9出现的次数是相同的)

最后再减去每一位出现的前导零即可

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional>
    
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) 

using namespace std;

typedef double db;
typedef long double ldb;
typedef long long ll;
typedef long long LL;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;

const db eps = 1e-6;
const int mod = 998244353;
const int maxn = 2e5+100;
const int maxm = 2e6+100;
const int inf = 0x3f3f3f3f;
const db pi = acos(-1.0);

ll n;
ll dp[maxn];
ll po[maxn];
vector<ll> sv(ll n){
    ll len = 0;
    vector<ll>ans(10);
    for(int i = 0; i < 10; i++)ans[i] = 0;
    ll tmp = 0;
    ll x = n;
    while(n){
        ll d = n%10;
        n/=10;
        len++;
        for(int i = 0; i < 10; i++){
            if(d > i){
                ans[i] += po[len-1] + d*dp[len-1];
            }
            else if(d==i){
                ans[i] += d*dp[len-1]+tmp+1;
            }
            else{
                ans[i] += d*dp[len-1]; 
            }
        }
        tmp += d*po[len-1];
    }
    ll m = 1;
    while(x){
        ans[0]-=m;
        m*=10;
        x/=10;
    }
    return ans;
}

int main() {
    //dp[0] = 0;
    ll tmp = 1;
    po[0] = 1;
    for(int i = 1; i <= 18; i++){
        po[i] = 10*po[i-1];
        dp[i] = dp[i-1]*10 + po[i-1];
    }
    ll l, r;
    scanf("%lld %lld", &l,&r);
    //scanf("%lld",&r);
    vector<ll>v1(10),v2(10);
    v1=sv(l-1);
    v2=sv(r);
    for(int i = 0; i < 10; i++){
        printf("%lld\n",v2[i]-v1[i]);
    }
    return 0;

}
/*
15542

 */

 

51Nod 1042 数字0-9的数量(数位DP)

标签:题解   while   double   div   fun   tmp   ems   ++   span   

原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/10519565.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!