http://ac.jobdu.com/problem.php?cid=1039&pid=15
很水的数位dp题目,dp[pos] [sum] 表示有pos个自由位pos之前的1的个数为sum的解
我还专门给编写了check程序
#include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef long long ll; ll dp[11][110],digit[11]; ll dfs(int pos,int prefix,int doing) { if(pos<0) return prefix; if(!doing&&dp[pos][prefix]!=-1) return dp[pos][prefix]; int end=doing?digit[pos]:9; ll ret=0; for(int i=0;i<=end;i++) { ret+=dfs(pos-1,prefix+(i==1),doing&&i==end); } if(!doing) dp[pos][prefix]=ret; return ret; } ll cal(ll n) { if(n<=0) return 0; int pos=0; for(;n;n/=10) digit[pos++]=n%10; return dfs(pos-1,0,1); } ll check(ll n) { ll ret=0; for(ll i=1;i<=n;i++) { for(ll tmp=i;tmp;tmp/=10) if(tmp%10==1) ret++; } return ret; } int main() { memset(dp,-1,sizeof(dp)); ll l,r; while(scanf("%lld%lld",&l,&r)==2) { if(l>r) swap(l,r); printf("%lld\n",cal(r)-cal(l-1)); } return 0; }