题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3652
思路来源:http://blog.youkuaiyun.com/johsnows/article/details/52735679?locationNum=13
最重要的是状态定义吧,我们要知道前一位是否是1,或者前面是否存在13,还有取模的值
那么就用state保存三个状态:state==1表示前一位是1,state==2表示已经出现过13了,什么都没有是0
所以总的状态要一维表示是第几位数,一维表示状态,一维表示前面2位对13取模的值
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
typedef long long LL;
LL d[13][3][13];
int digit[13];
int DFS(int pos,int state,int mod,bool limit)
{//state==1表示前一位是1,state==2表示已经出现过13了,什么都没有是0
if(pos==-1){
if(mod==0&&state==2) return 1;
//取模为0,且出现过13
else return 0;
}
LL& ans=d[pos][state][mod];
if(!limit && ans!=-1) return ans;
int temp=0,up=limit?digit[pos]:9;
for (int i = 0; i <=up ; ++i)
{
int nstate=0;
if(state==1&&i==3) nstate=2;
if(i==1) nstate=1;
if(state==2) nstate=2;
temp+=DFS(pos-1,nstate,(mod*10+i)%13,limit&&i==digit[pos]);
}
if(!limit) ans=temp;
return temp;
}
LL solve(LL x)
{
int len=0;
while(x){
digit[len++]=x%10;
x/=10;
}
return DFS(len-1,0,0,true);
}
int main(int argc, char const *argv[])
{
LL n;
memset(d,-1,sizeof(d));
while(cin>>n)
cout<<solve(n)<<endl;
return 0;
}