B number 数位DP

题意很简单就是要你寻找数字含有13字串并且能够被13整除的数。

我自己的写法和大佬的做法都不一样,时间也比他们的慢很多 ,跑了(200+ms)。

大佬的博客:https://blog.csdn.net/libin56842/article/details/10026063

大佬的DP是三维,而我用了四维,但我认为我的好理解一些,虽然效率不高

dp[pos][pre][mod][flag],表示第pos位,前一位是pre,模为mod,是否出现过13这个字串。

代码:

///#include<bits/stdc++.h>
///#include<unordered_map>
///#include<unordered_set>
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<bitset>
#include<set>
#include<stack>
#include<map>
#include<new>
#include<vector>
#define MT(a,b) memset(a,b,sizeof(a));
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double pai=acos(-1.0);
const double E=2.718281828459;
const int MOD=1e9+7;
const int INF=0x3f3f3f3f;

int n,num[15],dp[15][15][15][2];

int dfs(int pos,int pre,int mod,bool lead,bool limit,bool flag)
{
    if(pos==0)      ///递归结束,判断是否正确
        return mod==0&&flag==1;
    if(!limit&&!lead&&dp[pos][pre][mod][flag]!=-1)      ///该状态已经被访问过
        return dp[pos][pre][mod][flag];
    int up=limit?num[pos]:9;        ///确定这一位的上限
    int ans=0;
    for(int i=0;i<=up;i++)
        ans+=dfs(pos-1,i,(mod*10+i)%13,lead&&i==0,limit&&i==num[pos],(i==3&&pre==1)||flag); ///继续递归
    if(!limit&&!lead)       ///记忆化
        dp[pos][pre][mod][flag]=ans;
    return ans;
}

int slove(int x)
{
    int sign=0;
    while(x)
    {
        num[++sign]=x%10;
        x=x/10;
    }
    memset(dp,-1,sizeof(dp));
    return dfs(sign,0,0,true,true,0);
}
int main()
{
    while(scanf("%d",&n)!=EOF)
        printf("%d\n",slove(n));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_42211531/article/details/86001982