版权声明:https://github.com/godspeedcurry 欢迎加好友哦 https://blog.csdn.net/qq_38677814/article/details/82526312
数位dp 比赛的时候写了个暴搜没加记忆化结果gg
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll num[30];
ll f[20][2][2][20];
ll dfs(int len,bool low,bool nzero,int used){
ll ret=0;
if(used==4) return 0;//如果用完了返回0
if(len==0) return 1;//搜到底说明这个数成立返回1
if(f[len][low][nzero][used]) return f[len][low][nzero][used];//记忆化
for(int i=0;i<=9;++i){
if(i>num[len]&&!low) break;//如果这个数不是低位并且大于当前数位上的数 直接break
ret+=dfs(len-1,low||i<num[len],i!=0,used+(i!=0));//往下一位搜 低位或者当前位数更小,非零,用掉一个非零的数
}
return f[len][low][nzero][used]=ret;//记忆化
}
ll cal(ll x){
int len=0;
while(x){
num[++len]=x%10;
x/=10;
}
memset(f,0,sizeof(f));
return dfs(len,false,true,0);//从len位开始 最高位 这个初始值其实无所谓写false也可以 用了0个
}
void solve(){
ll l,r;
cin>>l>>r;
cout<<cal(r)-cal(l-1)<<endl;
}
int main(){
int T;cin>>T;
while(T--){
solve();
}
return 0;
}