A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task is to calculate how many wqb-numbers from 1 to n for a given integer n.
Input
Process till EOF. In each line, there is one positive integer n(1 <= n <= 1000000000).
Output
Print each answer in a single line.
Sample Input
13 100 200 1000
Sample Output
1 1 2 2
题目大意: 统计1-n中所有含有13且能被13整除的数字的个数
思路 : dp[i][j][k]三位数组 分别表示数位 mod13 的模数 状态
状态定义 : 因为递归从高位到低位 且含有13
当前面数不含‘13’且结尾不为1时 k = 0
不含‘13’’且结尾为1时 K = 1;
前面含有‘13‘’’时 k = 2;
同时还要递归mod值 mod2 = mod*10+当前位数字
下面详解代码
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int dp[20][13][3]; ///数位 模数 状态
int d[15];
///这一位下标为pos
///这一位之前的余数为mod 这一位之前的状态
///have= 0 前面末尾不是1 have = 1 前面末尾是1
/// have= 2 前面含有13 受不受限 limit
///即当前位为第pos位,前面是否有13,
///前面数字组成的数余数为k时的个数
int dfs( int pos, int mod , int have, int limit)
{
if( pos <= 0 )
{
if( mod == 0 && have == 2 ) //当mod == 0 时说明该数可以整除13 have == 2说明含13
return 1; //否则返回0 不符条件
else
return 0;
}
if( !limit && dp[pos][mod][have] != -1 )
return dp[pos][mod][have];
int ans = 0;
int mod2, have2;
int k = limit? d[pos]:9;
for( int i = 0; i<=k; i++)
{
mod2 = (mod*10 + i)%13; ///前面数字的余数*10 + 当前i即为当前mod
have2 = have;
if( have == 0 && i == 1 ) //have更新
have2 = 1;
if( have == 1 && i == 3 )
have2 = 2;
if( have == 1 && i != 1 && i != 3)
have2 = 0;
ans += dfs( pos-1, mod2, have2 , limit&&( i == k ));
}
if( !limit ) dp[pos][mod][have] = ans;
return ans;
}
int solve( int n )
{
memset( d, 0, sizeof( d ));
int cnt = 1;
while( n > 0 )
{
d[cnt++] = n%10;
n = n/10;
}
int ans = dfs( cnt-1, 0, 0, 1);
return ans;
}
int main()
{
int n;
while( scanf("%d", &n ) != EOF )
{
memset( dp, -1, sizeof( dp ));
int ans = solve( n );
printf("%d\n", ans );
}
return 0;
}