[Weekend training] digital counting

topic

[Memory Limit: $ 512MiB $]  [Time limit: $ 1000ms $]
O [Standard]   [Title Type: Traditional]   [Evaluation method: Text Comparison]

Description [title]

From the original title: ZJOI 2010

Given two positive integers $ a $ and $ b $ , seeking the $ [a, b] $ of all integers, each digital $ (digit) $ each appeared many times.

[Input Format]

Row contains only two integers  , the meanings indicated above.

[Output format]

$ 10 $ line contains integers, respectively, $ 9 $ 0 ~ $ at $ [a, b] appears many times in.

[Sample]

Sample input

1 99

Sample Output

9 20 20 20 20 20 20 20 20 20

【data range】

Data of $ 30% $, $ a, b \ in [1,10 ^ 6] $

Data of $ 100% $, $ a, b \ in [1,10 ^ {12}] $


 

answer

[Experience] do title

When solving the problem, if not the teacher said it was a $ dp $ title, I may also search directly on the storm , although my last storm also found positive solutions codes

First, I tried a bit of push data found or multi-miss, but always have no idea what is the connection between this title and the $ dp $.

I then two of a smear of

[Correct]

This is a digital $ dp $ title

On a stroll in the valley a few times, still found a big brother to write $ dp $ positive solutions (orz worship Gangster) , but I'm pretty stupid, do not understand the origins of $ dp $ (my konjac $ dp $ will in this way the), tears, she found the practice of search.

First, we put problems into it, and do with Qi Lu promise number the same way, the subject of the request of the interval $ [a, b] $ becomes the interval $ [1, b] $ with the interval $ [1, a- 1] $ in the number of digital arise.

Now we have to solve is how to find the interval $ [1, k] of each number $ emergence of the digital.

I look at the $ dfs $ part of it

int dfs(int len,bool small,int sum,bool prezero,int d){
    if(len==0)return sum;int ret=0;
    for(int i=0;i<10;++i){
        if(small&&i>num[len])break;
        ret+=dfs(len-1,small&&(i==num[len]),sum+((!prezero||i>0)&&(i==d)),prezero&&(i==0),d);
    }
    return ret;
}

The $ dfs $ feeling is not very clear ah.

Keke, I will explain, the $ dfs $ consists of five parameters, they are:

  • $ Len $: the first of several to enumerate the number of
  • $ Small $: the need for less than equal to the corresponding digits to the right boundary
  • $ Sum $: Obviously, there are already a number of cases
  • $ Prezero $: whether the current structure of the number with leading $ 0 $
  • $ D $: Digital current inquiry

Of which $ small $ may be a bit difficult to understand, here we can give an example

We assume that the right boundary $ k = 1388 $

The current structure of our number is $ Num = \ overline {13ix} $ ($ x $ is we do not have to enumerate the number of bits)

Obviously, $ i≤8 $, otherwise $ Num $ more than the right boundary

And that's $ small $ usefulness

Solve this problem, the next question is, will face search - the time complexity

Obviously, if the code is the bare cross, it will be $ T $ to fly

So we need to add memory to reduce most of repeated search operations

And here the memory of all parameters in fact just need to search the entire index into the definition and on it (as the title of this range very friendly)

Then there is the memory of $ dp [len] [small] [sum] [prezero] $, which is defined in the corresponding search parameters

Because we are sub-word search, so the last one dimension can be omitted

Then the code is your favorite

#include<bits/stdc++.h>
using namespace std;
#define int long long
template<class T>inline void qread(T& x){
    char c;bool f=false;x=0;
    while((c=getchar())<'0'||'9'<c)if(c=='-')f=true;
    for(x=(c^48);'0'<=(c=getchar())&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    if(f)x=-x; 
}
template<class T,class... Args>inline void qread(T& x,Args&... args){qread(x),qread(args...);}
inline int rqread(){
    char c;bool f=false;int x=0;
    while((c=getchar())<'0'||'9'<c)if(c=='-')f=true;
    for(x=(c^48);'0'<=(c=getchar())&&c<='9';x=(x<<1)+(x<<3)+(c^48));
    return f?-x:x;
}
const int MAXSIZE=20;
int l,r,num[MAXSIZE+5];
int dp[MAXSIZE+5][2][MAXSIZE+5][2];
int dfs(int len,bool small,int sum,bool prezero,int d){
    if(len==0)return sum;
    if(dp[len][small][sum][prezero]!=-1)return dp[len][small][sum][prezero];
    int ret=0;
    for(int i=0;i<10;++i){
        if(small&&i>num[len])break;
        ret+=dfs(len-1,small&&(i==num[len]),sum+((!prezero||i>0)&&(i==d)),prezero&&(i==0),d);
    }
    return dp[len][small][sum][prezero]=ret;
}
inline int solve(int var,int d){
    int len=0;
    memset(dp,-1,sizeof dp);
    while(var)num[++len]=var%10,var/=10;
    return dfs(len,1,0,1,d);
}
signed main(){
//    freopen(".in","r",stdin);
//    freopen(".out","w",stdout);
    qread(l,r);
    for(int i=0;i<10;++i)printf("%lld ",solve(r,i)-solve(l-1,i));
    putchar('\n');
    return 0;
}

Guess you like

Origin www.cnblogs.com/MachineryCountry/p/11612360.html