数位DP_HDU 3652

寻找[0,a]中,既包含"13"又能被13整除的数字的个数(a是每一个输入)

开始的思路是打表过,虽然时间再打表的时候时间长一些,但是应该是可以过的,我自己没有试

我使用的方法:

自己第一个想的思路是,记录下当前状态的余数,当前会否包含"13",每次保存的状态都是这样的,但是这样样例都过不了.......后来一想后面的数字和前面连接判断是否包含"13"的话,如果我前面状态保存的是一个"1"呢?那岂不是没有考虑后面再是"3"的情况,所以将是否包含“13”这一个条件分为三个条件:(1)是否包含13  (2)最后一位为1  (3)最后一位不为1

这样就解决了这个问题,我个人觉得数位DP比较难得地方就在于后面状态和前面状态相互对应时条件的判定

这个题中还有一个数学的小技巧:大整数取模 

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <math.h>
#include <queue>
#define INF 0x3f3f3f3f
#define ll long long
using namespace std;
int n , dp[12][3][13];//状态相同的判断:上一个位置的数字与1判断是否相同,是否都会被13整除,前面位数对于13的余数是否相同
int a[12];
int dfs(int pos, int has,int mod,bool limit)//has:有没有13 、 mod 取模13的余数(大数取模)!
{
    if(pos == -1) return has == 2&& mod == 0;
    if(!limit && dp[pos][has][mod] != -1) return dp[pos][has][mod];
    int up = limit?a[pos]:9;
    int ans = 0;
    for(int i = 0;i <= up;i ++)
    {
        int temp;
        if (has == 2 || (has == 1 && i == 3)) temp = 2;
        else if(i == 1) temp = 1;
        else temp = 0;
        ans += dfs(pos-1, temp ,(mod * 10 + i) % 13 ,limit && i==a[pos]);
    }
    if(!limit) dp[pos][has][mod] = ans;
    return ans;
}

int Solve(int x)
{
    int pos = 0;
    while(x)
    {
        a[pos++] = x % 10;
        x /= 10;
    }
    return dfs(pos-1,0,0,true);
}
int main()
{
    memset(dp,-1,sizeof(dp));
    while(~scanf("%d",&n))
    {
        printf("%d\n",Solve(n));
    }
}

猜你喜欢

转载自blog.csdn.net/li1615882553/article/details/80207913
今日推荐