#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 ",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 ",f(m)-f(n-1)); } return 0;}