bzoj1833: [ZJOI2010]count 数字计数 数位dp

bzoj1833
Description
给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次。
Input
输入文件中仅包含一行两个整数a、b,含义如上所述。
Output
输出文件中包含一行10个整数,分别表示0-9在[a,b]中出现了多少次。

单独考虑每一位,数位dp,注意前导零

/**************************************************************
    Problem: 1833
    User: walfy
    Language: C++
    Result: Accepted
    Time:72 ms
    Memory:1356 kb
****************************************************************/
 
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define cd complex<double>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)
 
using namespace std;
 
const double eps=1e-6;
const int N=20000+10,maxn=500000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;
 
int dight[20];
ll dp[20][20][10][2];
ll dfs(int id,int sum,int who,bool zero,int fp)
{
    if(!id)
    {
        return sum;
    }
    if(!fp&&dp[id][sum][who][zero]!=-1)return dp[id][sum][who][zero];
    int fpmax=fp?dight[id]:9;
    ll ans=0;
    for(int i=0;i<=fpmax;i++)
    {
        if(i==who&&zero)ans+=dfs(id-1,sum+1,who,zero|i,fp&&i==fpmax);
        else ans+=dfs(id-1,sum,who,zero|i,fp&&i==fpmax);
    }
    if(!fp)dp[id][sum][who][zero]=ans;
    return ans;
}
ll ans[10];
int main()
{
    ll a,b;
    scanf("%lld%lld",&a,&b);
    memset(dp,-1,sizeof dp);
    int cnt=0;
    while(b)
    {
        dight[++cnt]=b%10;
        b/=10;
    }
    ans[0]+=dfs(cnt,0,0,0,1);
    for(int i=1;i<=9;i++)
        ans[i]+=dfs(cnt,0,i,1,1);
    a--;
    if(a>=1)
    {
        memset(dp,-1,sizeof dp);
        cnt=0;
        while(a)
        {
            dight[++cnt]=a%10;
            a/=10;
        }
        ans[0]-=dfs(cnt,0,0,0,1);
        for(int i=1;i<=9;i++)
            ans[i]-=dfs(cnt,0,i,1,1);
    }
    for(int i=0;i<9;i++)printf("%lld ",ans[i]);
    printf("%lld\n",ans[9]);
    return 0;
}
/********************
 
********************/

猜你喜欢

转载自www.cnblogs.com/acjiumeng/p/9292755.html