模板http://www.cnblogs.com/jffifa/archive/2012/08/17/2644847.html
完全理解以后,我发现这种写法实在是太厉害了,简洁,优美,可以回避很多细节问题,而这些细节如果用递推的方法写,处理起来可能会非常痛苦
http://acm.hdu.edu.cn/showproblem.php?pid=2089
不要62
http://www.cnblogs.com/xiaohongmao/p/3473599.html
前几天写过这道题的解题报告,两种解法都有
http://acm.hdu.edu.cn/showproblem.php?pid=3555
不要49
#include <iostream> using namespace std ; typedef __int64 ll ; ll dp[25][2] ; int digit[25] ; ll dfs(int i,int s,bool e) { if(!i)return 1 ; if(!e && dp[i][s]!=-1) return dp[i][s] ; ll res=0 ; int u=e?digit[i]:9 ; for(int d=0 ;d<=u ;d++) { if(s && d==9) continue ; res+=dfs(i-1,d==4,e&&d==u) ; } return e?res:dp[i][s]=res ; } int callen(ll n) { int cnt=0 ; while(n) { cnt++ ; n/=10 ; } return cnt ; } void caldigit(ll n,int len) { memset(digit,0,sizeof(digit)) ; for(int i=1 ;i<=len ;i++) { digit[i]=n%10 ; n/=10 ; } } ll solve(ll n) { int len=callen(n) ; caldigit(n,len) ; return dfs(len,0,1) ; } int main() { int t ; scanf("%d",&t) ; memset(dp,-1,sizeof(dp)) ; while(t--) { ll n ; scanf("%I64d",&n) ; printf("%I64d\n",n+1-solve(n)) ; } return 0 ; }
http://acm.hdu.edu.cn/showproblem.php?pid=3652
出现13且是13的倍数
#include <iostream> using namespace std ; int dp[15][15][2][15] ;//当前位数 被13除的余数 是否包括13 最末一位数 int digit[15] ; int dfs(int i,int re,bool flag,int last,bool e) { if(!i)return !re && flag ; if(!e && dp[i][re][flag][last]!=-1) return dp[i][re][flag][last] ; int res=0 ; int u=e?digit[i]:9 ; for(int d=0 ;d<=u ;d++) res+=dfs(i-1,(re*10+d)%13,flag || (last==1 && d==3),d,e && d==u) ; return e?res:dp[i][re][flag][last]=res ; } int callen(int n) { int cnt=0 ; while(n) { cnt++ ; n/=10 ; } return cnt ; } void caldigit(int n,int len) { for(int i=1 ;i<=len ;i++) { digit[i]=n%10 ; n/=10 ; } } int solve(int n) { int len=callen(n) ; caldigit(n,len) ; return dfs(len,0,0,0,1) ; } int main() { int n ; memset(dp,-1,sizeof(dp)) ; while(~scanf("%d",&n)) { printf("%d\n",solve(n)) ; } return 0 ; }
http://acm.hdu.edu.cn/showproblem.php?pid=4389
和上一题很像,要求x整除f(x),由于f(x)范围较小,枚举f(x)就好,注意的地方是有点卡内存,数组要开的比较合适才能过,习惯性开大点会MLE
#include <iostream> #include <cstdio> #include <cstring> using namespace std ; int digit[11] ; int dp[11][84][84][84] ; int w ; int dfs(int i,int s,int mod,int e) { if(!i)return !mod && s==w ; if(!e && dp[i][s][mod][w]!=-1)return dp[i][s][mod][w] ; int u=e?digit[i]:9 ; int res=0 ; for(int d=0 ;d<=u ;d++) res+=dfs(i-1,s+d,(mod*10+d)%w,e && d==u) ; return e?res:dp[i][s][mod][w]=res ; } int callen(int n) { int cnt=0 ; while(n) { cnt++ ; n/=10 ; } return cnt ; } void caldigit(int n,int len) { memset(digit,0,sizeof(digit)) ; for(int i=1 ;i<=len ;i++) { digit[i]=n%10 ; n/=10 ; } } int solve(int n) { int len=callen(n) ; caldigit(n,len) ; int ans=0 ; for(w=1 ;w<84 ;w++) ans+=dfs(len,0,0,1) ; return ans ; } int main() { memset(dp,-1,sizeof(dp)) ; int t ; scanf("%d",&t) ; for(int cas=1 ;cas<=t ;cas++) { int l,r ; scanf("%d%d",&l,&r) ; printf("Case %d: %d\n",cas,solve(r)-solve(l-1)) ; } return 0 ; }
http://acm.hdu.edu.cn/showproblem.php?pid=3709
枚举平衡位置
#include <iostream> #include <cstdio> #include <cstring> using namespace std ; typedef __int64 ll ; int digit[25] ; ll dp[25][25][1500] ; int w ; ll dfs(int i,int s,int e) { if(!i)return !s ; if(!e && dp[i][w][s]!=-1)return dp[i][w][s] ; int u=e?digit[i]:9 ; ll res=0 ; for(int d=0 ;d<=u ;d++) res+=dfs(i-1,s+d*(i-w),e && d==u) ; return e?res:dp[i][w][s]=res ; } int callen(ll n) { int cnt=0 ; while(n) { cnt++ ; n/=10 ; } return cnt ; } void caldigit(ll n,int len) { memset(digit,0,sizeof(digit)) ; for(int i=1 ;i<=len ;i++) { digit[i]=n%10 ; n/=10 ; } } ll solve(ll n) { int len=callen(n) ; caldigit(n,len) ; ll ans=0 ; for(w=1 ;w<=len ;w++) ans+=dfs(len,0,1) ; return ans-len+1 ; } int main() { memset(dp,-1,sizeof(dp)) ; int t ; scanf("%d",&t) ; while(t--) { ll l,r ; scanf("%I64d%I64d",&l,&r) ; printf("%I64d\n",solve(r)-solve(l-1)) ; } return 0 ; }
http://acm.hdu.edu.cn/showproblem.php?pid=4722
和4389一样,不过除数只有10一个,更简单
#include <iostream> #include <cstdio> #include <cstring> using namespace std ; typedef __int64 ll ; int digit[25] ; ll dp[25][105][15] ; ll dfs(int i,int s,int mod,int e) { if(!i)return !mod ; if(!e && dp[i][s][mod]!=-1)return dp[i][s][mod] ; int u=e?digit[i]:9 ; ll res=0 ; for(int d=0 ;d<=u ;d++) res+=dfs(i-1,s+d,(mod+d)%10,e && d==u) ; return e?res:dp[i][s][mod]=res ; } int callen(ll n) { int cnt=0 ; while(n) { cnt++ ; n/=10 ; } return cnt ; } void caldigit(ll n,int len) { memset(digit,0,sizeof(digit)) ; for(int i=1 ;i<=len ;i++) { digit[i]=n%10 ; n/=10 ; } } ll solve(ll n) { int len=callen(n) ; caldigit(n,len) ; return dfs(len,0,0,1) ; } int main() { memset(dp,-1,sizeof(dp)) ; int t ; scanf("%d",&t) ; for(int cas=1 ;cas<=t ;cas++) { ll l,r ; scanf("%I64d%I64d",&l,&r) ; printf("Case #%d: %I64d\n",cas,solve(r)-solve(l-1)) ; } return 0 ; }