B-number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5802 Accepted Submission(s): 3344
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要49多了个取余的运算
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; int a[20]; long long dp[15][2][12][15]; long long dfs(int pos,bool pre,int status,bool last,int ha)//ha是余数 { int i; if (pos==-1) return (pre&&ha==0); if (!last && dp[pos][pre][status][ha]!=-1) return dp[pos][pre][status][ha]; int len=last?a[pos]:9; long long ans=0; for (i=0;i<=len;i++) { if (status==1 && i==3) ans+=dfs(pos-1,true,i,last && (i==len),(ha*10+i)%13); else ans+=dfs(pos-1,pre,i,last && (i==len),(ha*10+i)%13); } if (!last) { dp[pos][pre][status][ha]=ans; } return ans; } long long Cal(long long t) { int i,j,pos=0; while(t) { a[pos++]=t%10; t/=10; } return dfs(pos-1,0,0,1,0); } int main() { int i,j; __int64 n; while(scanf("%I64d",&n)!=-1) { memset(dp,-1,sizeof(dp)); printf("%I64d\n",Cal(n)); } return 0; }