这是数位的dp的基础题型,通过解析这道题可以了解到数位dp的基本板子,以前学长还讲过这个,现在拿到一道数位dp的题基本不会。。。希望以后可以改变这种情况。。。
#include <stdio.h> #include <stdlib.h> #include <iostream> #include <algorithm> #include <queue> #include <vector> #include <math.h> #include <string.h> using namespace std; #define INF 0x3f3f3f3f #define N 20 #define mid 1e-8 #define LL long long /********************************************************/ LL dp[N][N][N], d[N]; LL dfs(int now, int w, int tot, int fp)///now为当前的数字是第几位,w为当前的数字,tot为目前出现1的次数,fp为当前位是否达到上限值 { if(now==1) return tot;///搜索结束 if(!fp&&dp[now][w][tot]!=-1) return dp[now][w][tot];///达到上限值返回 int ma=(fp?d[now-1]:9);///设置上限 LL ans=0; for(int i=0;i<=ma;i++) ans+=dfs(now-1, i, tot+(i==1?1:0), fp&&i==ma);///搜索下一位 if(!fp&&dp[now][w][tot]==-1) dp[now][w][tot]=ans;///达到上限存储当前值 return ans; } LL solve(LL x) { if(x==0) return 0; LL X=x, sum=0; int len=0; while(X)///读取x的位数 { d[++len]=X%10;///存储每一位作为上限 X/=10; } for(int i=0;i<=d[len];i++) sum+=dfs(len, i, (i==1?1:0), i==d[len]);///暴力求解 return sum; } int main() { LL m, n; while(scanf("%lld%lld", &n, &m)!=EOF) { memset(dp, -1, sizeof(dp)); printf("%lld ", solve(m)-solve(n-1)); } return 0; }