【玲珑 OJ 1067 Digital Count】+ 数位 dp

来源:互联网 发布:薛之谦淘宝店铺地址 编辑:程序博客网 时间:2024/06/01 09:03

1067 - Digital Count
Time Limit:1s Memory Limit:1024MByte

Submissions:507Solved:111

DESCRIPTION
Given three integers a, b, P, count the total number of digit P appearing in all integers from a to b.

INPUT
The first line is a single integer
T
T, indicating the number of test cases.

For each test case:

There are only three numbers
a
,
b
,
P
a,b,P (0≤a≤b≤231-1, 0 < P < 10).
OUTPUT
For each test cases:

Print the total appearances of digit
P
P from
a
a to
b
b in a single line.
SAMPLE INPUT
2
1 10000 1
1 10 1
SAMPLE OUTPUT
4001
2
SOLUTION

玲珑杯”ACM比赛 Round #6

题意 : 统计 l ~ r 内数字 o 出现了多少次

思路 : 数位 dp

AC代码:

#include<cstdio>#include<cstring>using namespace std;typedef long long LL;int s[20];LL dp[30][30],p;LL js(int n,int a,int b,int c,int k){    if(n < 0){        if(!c) return a;        return k >= p ? 1 : 0;    }    if(!c && !b && dp[n][a] != -1) return dp[n][a]; // 剪枝,当不是临界值或者第一追溯时,不必再计算    int z = b ? s[n] : 9; // 临界    LL ans = 0;    for(int i = 0; i <= z; i++){        if(c && !i) ans += js(n - 1,0,b && i == z,1,k); // 第一次追溯        else if(i == p) ans += js(n - 1,a + 1,b && i == z,0,k); // 统计数再次出现        else  ans += js(n - 1,a,b && i == z,0,k);    }    if(!c && !b) dp[n][a] = ans; // 剪枝    return ans;}LL sl(LL a){    if(a < p) return 0;    if(a >= p && a <= 9) return 1;    memset(dp,-1,sizeof(dp));    int m  = 0;    while(a){        s[m++] = a % 10;        a /= 10;    }    return js(m - 1,0,1,1,0);}int main(){    int T,nl = 0;    LL n,m;    scanf("%d",&T);    while(T--){        scanf("%lld %lld %lld",&n,&m,&p);        printf("%lld\n",sl(m) - sl(n - 1));    }    return 0;}
0 0