hdu 3652 B-number 数位dp

题目:点击打开链接

题意:求小于n,是13的倍数且含有'13'的数的个数。n《1e9

分析:看了别人的才写出来,点击打开链接,因为要两个要求,不含13且不是13的倍数,这样的话,可是可以用三维数组表示状态f[i][j][k],铁打不变的是i表示数位,然后增加上用j表示余数,k表示是否含有13。然后dfs,从高位开始以此判断每一位的状态,

#include
#include
#include
#include
using namespace std;
const int N=15;
int bit[N],f[N][N][3];
/*
dp[i][j][k] j表示余数
k==0 不包含13且不以1结尾
k==1 不包含13且以1结尾
k==2 包含13
*/
int dfs(int pos,int mod,int have,bool lim)//第几位数,余数,状态标号,是否是上限
{
    if(pos<=0)return mod==0&&have==2;
    if(!lim&&f[pos][mod][have]!=-1)return f[pos][mod][have];
    int num=lim?bit[pos]:9;
    int ans=0;
    for(int i=0;i<=num;i++){
        int mod_x=(mod*10+i)%13; //传到下一位的余数,模拟除法的过程
        int have_x=have;
        if(have==0&&i==1)have_x=1;//末尾不是1,再加一位是1,标记为1
        if(have==1&&i!=1)have_x=0;//末尾是1,再加一位不是1,标记为0
        if(have==1&&i==3)have_x=2;//末尾是1,再加一位是3,标记为2
        ans+=dfs(pos-1,mod_x,have_x,lim&&i==num);
    }
    if(!lim)f[pos][mod][have]=ans;
    return ans;
}
int main()
{
    int n,len;
    while(~scanf("%d",&n)){
        memset(f,-1,sizeof(f));
        len=0;
        while(n){
            bit[++len]=n%10;
            n/=10;
        }
        printf("%d\n",dfs(len,0,0,1));
    }
    return 0;
}



你可能感兴趣的:(————动态规划————)