每天一个数位DP,做熟练了为止
题目链接:HDOJ3652
题意:求【1,n】中,能够被13整除且含有“13”字符串的数的个数
分析:
首先把问题变简单一点,含有“13”字符串怎么处理?废话了嘛,就是模板啊,处理过49,处理过62,一个套路
那么怎么在这个基础上处理被13整除呢?
很简单,加一维变量,mod为从高位到当前位的数值和,模13的余数
即:dp【pos】【status】【mod】添加一维dp变量
然后上模板
__int64 n;
int digit[20];
__int64 dp[20][5][15];
__int64 dfs(int pos,int status,int mod,bool flag){
if (pos==0) return (status==2&&mod==0);
if (flag&&dp[pos][status][mod]!=-1) return dp[pos][status][mod];
int num=flag?9:digit[pos];
__int64 ans=0;
for(int i=0;i<=num;i++){
int nowmod=(mod*10+i)%13;
if (status==2||(status==1&&i==3)) ans+=dfs(pos-1,2,nowmod,flag||i<num);
else if (i==1) ans+=dfs(pos-1,1,nowmod,flag||i<num);
else ans+=dfs(pos-1,0,nowmod,flag||i<num);
}
if (flag) dp[pos][status][mod]=ans;
return ans;
}
__int64 calc(__int64 n){
//标准格式
//将n分解成各个数位,从高到低
memset(digit,0,sizeof(digit));
int pos=0;
while(n){
digit[++pos]=n%10;
n/=10;
}
return dfs(pos,0,0,0);
}
int main(){
//input;
memset(dp,-1,sizeof(dp));
while(scanf("%I64d",&n)!=EOF)
printf("%I64d\n",calc(n));
return 0;
}