又是一个数位dp入门题,求1到n中含有13作为子串而且能被13整除的数的个数
dp状态dp[pos][pre][mod][have]定义为当之前的前缀的状态是这个的时候,后面可以接上的使得接上之后成为符合题意的后缀的个数
具体见代码吧
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 15;
int dp[maxn][maxn][maxn][maxn];
int dig[maxn];
int dfs(int pos,int pre,int mod,bool have,bool bound){
if(pos < 0) return have && !mod;
int & dpnow = dp[pos][pre][mod][have];
if(!bound && dpnow != -1) return dpnow;
int ret = 0;
int upd = bound ? dig[pos] : 9;
for(int i=0;i<=upd;i++){
if(pre == 1 && i == 3) ret += dfs(pos-1,i,(mod * 10 + i)%13,1,bound && (i==upd));
else ret += dfs(pos-1,i,(mod * 10 + i ) %13,have,bound && (i==upd));
}
if(!bound)
dpnow = ret;
return ret;
}
int cal(int n){
int len = 0;
while(n){
dig[len++] = n % 10;
n /= 10;
}
return dfs(len-1,0,0,0,1);
}
int main(){
int n;
memset(dp,-1,sizeof(dp));
while(~scanf("%d",&n)){
printf("%d\n",cal(n));
}
return 0;
}

本文介绍了一种使用数位DP方法解决含有特定子串且能被特定数整除的问题。通过定义状态转移方程,计算1到n之间符合条件的数的个数。代码中详细展示了状态转移过程及核心实现细节。
490

被折叠的 条评论
为什么被折叠?



