hdu4389(記憶優化,數位dp)
阿新 • • 發佈:2019-01-22
題意:
給定一個範圍,求這個範圍中滿足以下條件的數的個數:這個數要滿足這個數本身能整出這個數各個位上數的和。
題解:
狀態很難想!!dp[pos][sum][mod][res] 前pos位和為sum模以mod結果為res的個數
我用的記憶搜尋,比遞推好理解多了。
列舉取模的數,搜尋到深度底部是判斷如果結果res=0&&sum==mod時返回1.
#include<stdio.h> #include<string.h> #include<algorithm> #include<iostream> #include<math.h> using namespace std; typedef __int64 lld; #define oo 0x3f3f3f3f #define digit 11 #define maxn 82 int dp[digit][maxn][maxn][maxn]; int bit[digit]; int dfs(int pos,int sum,int mod,int res,int f) { if(pos<1) return (res==0&&sum==mod); if(!f&&dp[pos][sum][mod][res]!=-1) return dp[pos][sum][mod][res]; int last=f?bit[pos]:9; int ans=0; for(int i=0;i<=last;i++) { ans+=dfs(pos-1,sum+i,mod,(res*10+i)%mod,f&&i==last); } if(!f) dp[pos][sum][mod][res]=ans; return ans; } int Cnt(int n) { int len=0; while(n) { bit[++len]=n%10; n/=10; } int ans=0; for(int i=1;i<=81;i++) ans+=dfs(len,0,i,0,1); return ans; } int main() { int T,a,b; scanf("%d",&T); memset(dp,-1,sizeof dp); for(int cas=1;cas<=T;cas++) { scanf("%d %d",&a,&b); printf("Case %d: %d\n",cas,Cnt(b)-Cnt(a-1)); } return 0; } /* 100 1 100000000 */