B-number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3526 Accepted Submission(s): 1983
Problem Description
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
题目大意是给定一个数字,求这个数字范围内的含有13的且可以被13整除的数的个数
第一想法是跟Bomb那个题目一样去做,取一个fir_1找是否含有13的,但是做起来发现一个问题就是那个题目与这个题目差别在于当那个题目我知道有13以后,后面的数再取什么都可以不用管了,直接加上后面的数位的个数这么大的数量级就可以。但是对于这个题我们需要保存已经包含13这个数的这个状态,没有办法,只好升级维数,不过因为只有两个状态,所以空间并没有什么影响~
构造这样一个dp[i][j][k][l]这么一个数组,i表示的是pos,j表示的是余数,k表示的是当前位上一位的数是否为1,l表示的是是否已经含有13。
之后的处理比较简单,就是Bomb多了个取余的运算。
代码如下:
/*************************************************************************
> File Name: B-number.cpp
> Author: Zhanghaoran
> Mail: chilumanxi@xiyoulinux.org
> Created Time: Sat 14 Nov 2015 12:52:50 AM CST
************************************************************************/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
long long x;
long long dp[15][15][2][2];
int num[15];
long long work(int ,int ,int ,bool, bool);
long long calc(long long x){
int i = 1;
while(x){
num[i ++] = x % 10;
x /= 10;
}
return work(i - 1, 0, 0, 0, 1);
}
long long work(int pos, int rem, int fir_1, bool fir_13, bool flag){
if(pos == 0){
if(fir_13 && !rem)
return 1;
else
return 0;
}
if(!flag && dp[pos][rem][fir_1][fir_13] != -1)
return dp[pos][rem][fir_1][fir_13];
long long ans = 0;
int temp = flag ? num[pos] : 9;
for(int i = 0; i <= temp; i ++){
if(fir_13){
ans += work(pos - 1, (rem * 10 + i) % 13, i == 1, 1, flag && i == temp);
}
else{
if(fir_1 && i == 3)
ans += work(pos - 1, (rem * 10 + i) % 13, 0, 1, flag && i == temp);
else
ans += work(pos - 1, (rem * 10 + i) % 13, i == 1, 0, flag && i == temp);
}
}
if(!flag && dp[pos][rem][fir_1][fir_13] == -1)
dp[pos][rem][fir_1][fir_13] = ans;
return ans;
}
int main(void){
memset(dp, -1, sizeof(dp));
while(~scanf("%lld", &x)){
cout << calc(x) << endl;
}
}