1. 程式人生 > >【codeforces 1036C】Classy Numbers(數位dp)

【codeforces 1036C】Classy Numbers(數位dp)

C. Classy Numbers time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandard output Let’s call some positive integer classy if its decimal representation contains no more than 3 non-zero digits. For example, numbers 4 , 200000 , 10203 are classy and numbers 4231 , 102306 , 7277420000 are not.

You are given a segment [ L ; R ] . Count the number of classy integers x such that L ≤ x ≤ R .

Each testcase contains several segments, for each of them you are required to solve the problem separately.

Input The first line contains a single integer T ( 1 ≤ T ≤ 10 4 ) — the number of segments in a testcase.

Each of the next T lines contains two integers L i and R i ( 1 ≤ L i ≤ R i ≤ 10 18 ).

Output Print T lines — the i -th line should contain the number of classy integers on a segment [ L i ; R i ] .

Example inputCopy 4 1 1000 1024 1024 65536 65536 999999 1000001 outputCopy 1000 1 0 2 solve:數位dp即可,記憶化一下,dfs傳入三個變數:pos(數位),num(當前還差幾個數就能達到3個非0數),limit(是否到達上界)。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
const int INF = 0x3f3f3f3f;
typedef long long ll;
typedef int INT ;
#define int long long
int digit[20];
int dp[20][30];
int dfs(int pos,int num,int limit){
    if(pos<0&&num>=0) return 1;
    if(pos<0||num<0) return 0;
    if(!limit&&dp[pos][num]) return dp[pos][num];

    int ans=0;
    int up=limit?digit[pos]:9;

    for(int i=0;i<=up;i++){
        ans+=dfs(pos-1,num-(i?1:0),limit&&i==up);
    } 
    if(!limit) dp[pos][num]=ans;
    return ans;
}

int solve(int x){
    int cnt=0;
    while(x){
        digit[cnt++]=x%10;
        x/=10;
    }
    return dfs(cnt-1,3,1);
}

INT main(){
    int t,a,b;
    cin>>t;
    while(t--){
        memset(dp,0,sizeof(dp));
        cin>>a>>b;
        cout<<solve(b)-solve(a-1)<<endl;
    }
    return 0;
}