看了好久的数位dp ,今天才算有点明白 ,但目前还处入门水平 理解有限
这是个很好的入门题:
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
Input
输入的都是整数对n、m(0<n≤m<1000000),如果遇到都是0的整数对,则输入结束。
Output
对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。
Sample Input
1 100 0 0
Sample Output
80
数组dp[i][j] 表示以j为开头的i位数且既不包含4又不包含62的个数
则
dp[i][j] = 0 ( if j == 4 )
= dp[i-1][j] ( j = 1, 2 ,3 ....9 ) ( if j != 6 )
= dp[i-1][j] ( j = 1, 3, 4, ..9 ( if( j == 6 )
刚开始我对前导0有些疑惑 比如52 052 0052 但后来这么理解 在dp[2][5]中为 52 dp[3][0] 中为052 以此类推 他们都是各个数组中符合条件的一个数
我们以532为例看一下
先初始化dp数组 开始为0
dp[0][0] = 1我们提前设定
dp[1][0] = dp[0][1] + ....dp[0][9] = 1;
.....
dp[1][4] = 0;
dp[1][9] = dp[0][1] + ....dp[0][9] = 1;
dp[2] [1] = dp[1][0] +....dp[1][9] = 9 ( 即 10 11 12 13 15 ..19)
......
dp[2][9] = dp[1][0] +....dp[1][9] = 9 ( 即 90 91 92 93 95....99)
....
.....
若dp[4][2] = m
则dp[5][6]应注意 不能加dp[4][2]
总而言之 dp[i][j]就是位数已经确定 j开头也已经确定 数目就由后i-1位进行确定
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int dp[20][10];
int dig[10];
int init( )
{
memset( dp, 0, sizeof( dp ));
dp[0][0] = 1;
for(int i = 1; i<=20; i++) ///i位数
{
for(int j = 0; j<=9; j++) ///以j开头
{
if( j == 4 ) 不能有4
{
dp[i][j] = 0;
continue;
}
for(int k = 0; k<= 9; k++)
{
if( j != 6 || k != 2 ) 不能有连续62
{
dp[i][j] += dp[i-1][k];
// printf("%d\n", dp[i][j]);
}
}
}
}
}
long long int solve( int n ) ...求[ 0, n) 符合条件的个数
{
long long int ans = 0;
int cnt = 1;
while( n > 0 )
{
dig[cnt++] = n%10; 存取各位
n = n/10;
}
dig[cnt] = 0;
for( int i = cnt - 1; i >= 1 ; i--)
{
for(int j = 0; j<dig[i]; j++)
{
//printf("%d %d\n", i, j);
if( dig[i+1] != 6 || j != 2 ) 如果上一位不是6 才能加以2开头的
{
ans += dp[i][j];
//printf("%lld\n" , ans);
}
}
if( dig[i] == 4 || (dig[i+1] == 6 && dig[i] == 2 )) 如果这次为62下次肯定以62开头 所以直接break;
break;
}
return ans;
}
int main()
{
int a, b;
init();
while( scanf("%d%d", &a, &b) != EOF)
{
memset( dig, 0, sizeof( dig ));
if( a == 0 && b == 0 )
return 0;
long long int ans = solve( b+1 ) - solve(a);
printf("%lld\n" ,ans);
}
return 0;
}