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;
}