#include <iostream>
#include <cstring>
using namespace std;
const int M =15;
int s[M];
int dp[M][M][3];// dp[i][mod][staus] 枚举到第i位时 余数为mod 状态为staus
// staus:枚举到第i位 没出现13且末尾不为1,没出现13但末尾为1,出现过13
int dfs(int pos,int mod,int have,int limit)//flag表示是否有上界限制 比如965 前两位为96时第三为最多枚举到5
{
if(pos<1)
{
return mod==0&&have==2;//合法状态
}
if(!limit&&dp[pos][mod][have]!=-1)
{
return dp[pos][mod][have];
}
int up=limit?s[pos]:9;
int ans=0;
for(int i=0;i<=up;i++) //其实就时每位枚举,dp记录
{
int mod_x=(mod*10+i)%13;//竖式除法
int state=have;
if(state==0&&i==1)
{
state=1;
}
if(state==1&&i!=1&&i!=3)
{
state=0;
}
if(state==1&&i==3)
{
state=2;
}
ans+=dfs(pos-1,mod_x,state,limit&&(i==up)); //枚举下一位数
}
//输入有上界的限制
if(!limit)//这里对应上面的记忆化,在一定条件下时记录,保证一致性 ,与输入无关
{
dp[pos][mod][have]=ans;
}
return ans;
}
int main()
{
int n;
memset(dp,-1,sizeof(dp));//约束条件是每个数自身的属性,而与输入无关
while(cin>>n)
{
memset(s,0,sizeof(s));
int len=0;
while(n!=0)
{
s[++len]=n%10;
n/=10;
}
cout<<dfs(len,0,0,1)<<endl;
}
return 0;
}
hdu 3652 数位dp模版题
最新推荐文章于 2019-05-22 22:04:22 发布