题目链接:http://codeforces.com/problemset/problem/1036/C
题意:求出l-r范围内,数位上非零数字个数<=3的数字个数。
思路:因为状态只和非零数字有关,所以不用管前导0,那么两维数组,dp[i]][j]表示后面需要算的还有i位,前面非零数字已经有j个的时候,有多少个数字满足条件。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
ll dp[25][5];
int num[25];
ll dfs(int len,int sum,bool limit)
{
if(len==0)
return sum<=3;
if(sum>3) //剪枝操作
return 0;
if(!limit&&dp[len][sum]!=-1)
return dp[len][sum];
ll cnt=0,top=limit?num[len]:9;
for(int i=0;i<=top;i++)
{
cnt+=dfs(len-1,sum+(i!=0),limit&&i==top);
}
if(!limit)
dp[len][sum]=cnt;
return cnt;
}
ll solve(ll n)
{
int k=0;
while(n)
{
num[++k]=n%10;
n/=10;
}
return dfs(k,0,true);
}
int main()
{
ll l,r;
int t;
cin>>t;
memset(dp,-1,sizeof dp);
while(t--)
{
cin>>l>>r;
cout<<solve(r)-solve(l-1)<<endl;
}
return 0;
}