题意:给你一个区间,让你求区间里面数字的每一位数字都不递增或不递减的数的个数,比如1234,55543,432,11,4这些,求这些数的个数。
思路:数位dp,用dp[i][j][0or1]表示i位数字以j开头,0表示下降,1表示上升的满足题意的数的个数。用fu[i][j]表示i位以j开头的上升和下降重复的数的个数。要注意处理下降的数的时候得把以0开头的特殊记,否则转移方程写起来会更麻烦= =(因为我写的本来就比较麻烦T^T),后面的dp部分得仔细思考,然后其实没啥难的,主要是思路得清晰= =!
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include<string.h>
#include<vector>
#include<queue>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<map>
#include<stdlib.h>
#include<time.h>
#include<stack>
#include<set>
#include<deque>
using namespace std;
typedef long long ll;
ll dp[25][10][2],fu[25][10];///0递增1递减
void init()
{
memset(dp,0,sizeof(dp));
memset(fu,0,sizeof(fu));
for(int i=0; i<10; i++)
dp[1][i][0]=dp[1][i][1]=fu[1][i]=1;
for(int i=2; i<25; i++)
for(int j=0; j<10; j++)
for(int k=0; k<10; k++)
if(j<=k)
dp[i][j][0]+=dp[i-1][k][0];
for(int i=2; i<25; i++)
for(int j=0; j<10; j++)
for(int k=0; k<10; k++)
if(!j)
dp[i][j][1]+=dp[i-1][k][1];
else if(j>=k)
{
if(k)
dp[i][j][1]+=dp[i-1][k][1];
else
dp[i][j][1]++;
}
for(int i=2; i<25; i++)
for(int j=0; j<10; j++)
for(int k=0; k<10; k++)
if(!j)
fu[i][j]+=fu[i-1][k];
else
fu[i][j]=1;
/*for(int i=1;i<=5;i++)
for(int j=0;j<10;j++)
cout<<"fu["<<i<<"]["<<j<<"]="<<fu[i][j]<<endl;
*/
/*for(int j=1; j<=4; j++)
for(int i=0; i<10; i++)
cout<<"dp["<<j<<"]["<<i<<"][1]="<<dp[j][i][1]<<endl;
*/
}
ll get(ll x)
{
if(!x)
return 1;
else if(x>0&&x<10)
return (ll)(x+1);
int digit[25],bj=0;
while(x)
{
digit[bj++]=x%10;
x/=10;
}
//for(int i=0; i<bj; i++)
// cout<<digit[i]<<endl;
ll ans=0;
for(int i=bj-1; i>=0; i--)
{
int flag=0;
for(int j=bj-2; j>i; j--)
if(!flag&&digit[j+1]>digit[j])
flag=1;
else if(!flag&&digit[j+1]<digit[j])
flag=2;
else if(flag==1&&digit[j+1]<digit[j])
{
flag=-1;
break;
}
else if(flag==2&&digit[j+1]>digit[j])
{
flag=-1;
break;
}
if(flag==-1)
break;
int l=digit[i];
if(!i)l++;
//cout<<"i="<<i<<"-->l="<<l<<endl;
for(int j=0; j<l; j++)
{
//cout<<"j="<<j<<",flag="<<flag<<":";
if(!flag)
{
///ans+=(dp[i+1][j][0]+dp[i+1][j][1]-fu[i+1][j]);
if(i==bj-1||j==digit[i+1])
ans+=(dp[i+1][j][0]+dp[i+1][j][1]-fu[i+1][j]);//cout<<"dp["<<i+1<<"]["<<j<<"][0]+dp["<<i+1<<"]["<<j<<"][1]="<<dp[i+1][j][0]<<"+"<<dp[i+1][j][1]<<"-"<<fu[i+1][j]<<endl;
else if(j>digit[i+1])
ans+=dp[i+1][j][0];//cout<<"dp["<<i+1<<"]["<<j<<"][0]="<<dp[i+1][j][0]<<endl;
else
{
if(j)
ans+=dp[i+1][j][1];//cout<<"dp["<<i+1<<"]["<<j<<"][1]="<<dp[i+1][j][1]<<endl;
else
ans++;//cout<<"ans++"<<endl;
}
}
else if(flag==1)
{
if(j<=digit[i+1])
{
if(j)
ans+=dp[i+1][j][1];//cout<<"dp["<<i+1<<"]["<<j<<"][1]="<<dp[i+1][j][1]<<endl;
else ans++;//cout<<"dp["<<i+1<<"]["<<j<<"][1]="<<1<<endl;
}
}
else if(flag==2)
{
if(j>=digit[i+1])
ans+=dp[i+1][j][0];//cout<<"dp["<<i+1<<"]["<<j<<"][0]="<<dp[i+1][j][0]<<endl;
}
}
//cout<<ans<<endl;
}
//cout<<"*"<<ans<<endl;
return ans;
}
int main()
{
init();
int t;
scanf("%d",&t);
while(t--)
{
ll l,r;
scanf("%lld%lld",&l,&r);
ll ans1=get(l-1),ans2=get(r),ans=ans2-ans1;
printf("%d\n",ans);
}
return 0;
}