number(数位DP)

来源:互联网 发布:虚拟内存 知乎 编辑:程序博客网 时间:2024/06/05 23:00

原题链接
number

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5010 Accepted Submission(s): 2874

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

Author
wqb0039
这个题就是一个经典的数位DP问题,给出一个可能会特别特别大的数,让你求出满足某些条件的数的总和是多少,一般来说是可以整除某个质数或者是不含有某个数或者是必须含有某个数之类的,思路是一样的,无非就是增加判断的维数而已

//求1~n的范围里含有13且能被13整除的数字的个数#include <cstdio>#include <iostream>#include <cstring>#include <string>#include <algorithm>using namespace std;int dp[12][13][2][3];//dp[i][j][0]就代表的是总长度为len-i的所有数字中凡是所有模13为j的数字且前缀和小于前面的数字的所有数字的个数,0代表上一位什么//最后面的那个比普通数位dp多出来的维度x是当前列举的数,z是前一位的状态,1代表前一位是1,2代表找到13了,0代表不是特殊情况int mi[12]={1,10,9,12,3,4,1,10,9,12,3,4};//保存的是10的i次方的幂对37取模的结果//上面这个数组还可以继续扩大,这样做主要是便于快速进行幂运算,否则的话会超时/*mi[0]=1;        for(int i=1;i<12;i++)                mi[i]=(mi[i-1]*10) % 13;*/int cal(int x,int wei,int p){    return (x*mi[wei])%p;//如x=3,wei=4,37  那么这个方程返回的值就是30000对37的模}int cal2(int z,int x){        if(z==2) return 2;//把它放到最前面是因为这种情况在后期出现的概率最高,可以提高判断的效率        if(x==1) return 1;//不管前一位是什么,这一位是1下一位就一定是1        if(z==1 && x==3) return 2;//找到了13就要改变状态        return 0;//其他所有的情况都是不行的}int solve(string s){        memset(dp,0,sizeof(dp));        dp[0][0][1][0]=1;//这个初始状态就是说前缀和是满的情况下给一个初始值为1,但是原理还是需要去研究一下        int len=s.size();        for(int i=0;i<len;i++)        for(int j=0;j<13;j++)        for(int k=0;k<2;k++)        for(int z=0;z<3;z++)        if(dp[i][j][k][z]!=0){//自己已经是0了当然不用向后传递了                int r=(k==0? 9:s[i]-'0');                for(int x=0;x<=r;x++){                        dp[i+1][(j+cal(x,len-1-i,13))%13][(k==1 && x==r)? 1:0][cal2(z,x)] += dp[i][j][k][z];                }        }        return dp[len][0][0][2]+dp[len][0][1][2];}int main(){        string s;        while(cin >> s){                cout<<solve(s)<<endl;        }        return 0;}
0 0
原创粉丝点击