首页 > 代码库 > hdu 4722 数位dp

hdu 4722 数位dp

/*
数位dp
用记忆化搜索写很清爽啊!不用推状态转移方程good。
开一个二维数组用来储存前len状态对10取余,有10种状态0-9;
然后直接过一遍就行了
*/
#include<stdio.h>
#include<string.h>
#define ll __int64
#define N  20
ll digit[N],dp[N][11];
ll dfs(ll len,ll cnt,ll ok) {
  if(!len) {
      if(cnt==0)//如果可以整除返回1
        return 1;
  else return 0;
  }
  if(!ok&&dp[len][cnt]!=-1)//是否记忆过
    return dp[len][cnt];
  ll ans=0,i,maxx=ok?digit[len]:9;
  for(i=0;i<=maxx;i++)
        ans+=dfs(len-1,(cnt+i)%10,ok&&i==maxx);//ok和i==maxx记录是否是边界
  if(!ok)//记忆
    dp[len][cnt]=ans;
  return ans;
}
ll f(ll n) {
 ll len=0;
 while(n) {//统计
    digit[++len]=n%10;
    n/=10;
 }
 return dfs(len,0,1);
}
int main() {
      memset(dp,-1,sizeof(dp));
     ll n,m;
      int  t,k=0;
      scanf("%d",&t);
      while(t--) {
        scanf("%I64d%I64d",&n,&m);
        printf("Case #%d: %I64d\n",++k,f(m)-f(n-1));
      }
return 0;}

hdu 4722 数位dp