#include<stdio.h>
#include<string.h>
#define N 20
#define ll __int64
ll dp[N][N];//最多记忆400种情况
ll digit[N];
ll dfs(ll len,ll cnt,ll ok) {
if(!len) return cnt;
if(!ok&&dp[len][cnt]!=-1)
return dp[len][cnt];
ll i,ans=0,maxx=ok?digit[len]:9;
for(i=0;i<=maxx;i++) {
if(i==1)ans+=dfs(len-1,cnt+1,ok&&i==maxx);
else
ans+=dfs(len-1,cnt,ok&&i==maxx);
}
if(!ok)
dp[len][cnt]=ans;
return ans;
}
ll f(ll n) {
ll len=0;
while(n) {
digit[++len]=n%10;
n/=10;
}
return dfs(len,0,1);
}
int main() {
ll n,m,k;
memset(dp,-1,sizeof(dp));
while(scanf("%I64d%I64d",&n,&m)!=EOF) {
if(n>m) {
k=n;
n=m;
m=k;
}
printf("%I64d\n",f(m)-f(n-1));
}
return 0;}
<pre name="code" class="cpp">/*
数位dp
直接相加更快
另一种思路
*/
#include<stdio.h>
#include<string.h>
#define N 20
#define ll __int64
ll lower[N];//储存十的倍数。
ll dp[N][10];
ll digit[N];
ll rest[N];//用来储存有多少数
ll dfs(ll len,ll cnt,ll ok) {
if(!len) return cnt==1?1:0;
if(!ok&&dp[len][cnt]!=-1)
return dp[len][cnt];
ll i,ans=0,maxx=ok?digit[len]:9;
for(i=0;i<=maxx;i++)
ans+=dfs(len-1,i,ok&&i==maxx);
if(cnt==1) {
if(!ok)
ans+=lower[len];
else
ans+=rest[len];//
}
if(!ok)
dp[len][cnt]=ans;
return ans;
}
ll f(ll n) {
ll len=0;
ll z=n;
while(n) {
digit[++len]=n%10;
rest[len]=z%lower[len]+1;//比如是163的话,因为从100-163所以取余后要加一
n/=10;
}
return dfs(len,0,1);
}
int main() {
ll i,n,m;
lower[0]=1;
memset(dp,-1,sizeof(dp));
for(i=1;i<=19;i++)
lower[i]=lower[i-1]*10;
while(scanf("%I64d%I64d",&n,&m)!=EOF) {
printf("%I64d\n",f(m)-f(n-1));
}
return 0;}