【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;
}

猜你喜欢

转载自blog.csdn.net/duanghaha/article/details/82668690