Increasing or Decreasing
We all like monotonic things, and solved many problems about that like Longest Increasing Subsequence
(LIS). Here is another one which is easier than LIS (in my opinion).We say an integer is a momo number if its decimal representation is monotonic. For example, 123, 321,777 and 5566 are momo numbers; But 514, 50216 and 120908 are not.
Please answer m queries. The i-th query is a interval [li, ri], and please calculate the number of momo numbers in it.
Input
The first line contains an integer m.
Each of the following m lines contains two integers li , ri .
• 1 ≤ m ≤ 105
• 1 ≤ li ≤ ri ≤ 1018
Output
For each query, please output the number of momo numbers in that range.
Sample input
2
1 100
100 200
Sample output
100
48
题目大意:
定义一类momo number:各数位从高位到低位单调不减或者单调不增,给出L,R,问区间[L,R]之间momo number的数量。
我的做法是用数位DP统计从0到R,L-1的momo number,再相减得到答案。
至于如何得到0到N,我是先统计以x结尾长度为y的单调不升的方案数,和以x结尾长度为y的单调不降的方案数,然后先获得位数比当前数字位数低的momo number的数量,再从高位依次枚举到低位,枚举当前位的数字统计momo number的数量,统计方法是依次固定前几个高位的数字再枚举当前位的数字值就可以不重不漏的统计,但是要注意的是,如果前面固定的数字出现了先上升再下降或者先下降再上升的情况,就立即退出统计。
代码:
#include <bits/stdc++.h>
using namespace std;
inline void read(int &x){
char ch;
bool flag=false;
for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;
for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
x=flag?-x:x;
}
inline void read(long long &x){
char ch;
bool flag=false;
for (ch=getchar();!isdigit(ch);ch=getchar())if (ch=='-') flag=true;
for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());
x=flag?-x:x;
}
const int maxn=30;
int fdown[maxn][11];
int fup[maxn][11];
void prepare(){
for (int i=0;i<=9;i++)
{
fdown[1][i]=1;
fup[1][i]=1;
}
for (int i=1;i<=20;i++)
for (int j=0;j<=9;j++)
for (int k=j;k<=9;k++)
fdown[i][j]+=fdown[ i-1 ][k];
for (int i=1;i<=20;i++)
for (int j=0;j<=9;j++)
for (int k=0;k<=j;k++)
fup[i][j]+=fup[i-1][k];
}
int query(long long x){
if (x<=10)
return x+1;
int num[20];
int cnt=0;
long long tmp=1;
while (x)
{
num[++cnt]=x%10;
x=x/10;
tmp=tmp*10;
}
reverse(num+1,num+cnt+1);
int ans=0;
ans=query(tmp/10-1);
int op=0;
bool is=1;
for (int i=1;i<=cnt;i++)
{
bool vis1=0,vis2=0;
if (op!=1)
if (i!=1)
{
for (int j=0;j <=min( num[i-1] , num[i]-1) ;j++)
{
ans+=fup[cnt-i+1][j];
vis1=1;
}
}
else
for (int j=1;j < num[i];j++)
{
ans+=fup[cnt-i+1][j];
vis1=1;
}
//printf("down %d\n",ans);
if (op!=-1)
if (i!=1)
{
for (int j=num[i-1];j < num[i] ;j++)
{
//printf("%d %d\n",cnt-i+1,fdown[cnt-i+1][j]);
ans+=fdown[cnt-i+1][j];
vis2=1;
}
}
else
for (int j=1;j < num[i]; j++)
{
ans+=fdown[cnt-i+1][j];
//printf("%d %d\n",cnt-i+1,fdown[cnt-i+1][j]);
vis2=1;
}
//printf("up %d\n",ans);
if (op==0)
{
if (i!=1)
{
if ( num[i] < num[i-1])
op=-1;
if ( num[i] > num[i-1])
op=1;
}
}
if (i==1)
ans-=num[i]-1;
else
if ( vis1 && vis2)
ans--;
if (op==1)
{
if ( num[i] < num[i-1] )
{
is=0;
break;
}
}
if (op==-1)
{
if ( num[i] > num[i-1] )
{
is=0;
break;
}
}
//printf(" %d\n",ans);
}
if (is)
ans++;
return ans;
}
int main(){
//freopen("mine.out","w",stdout);
prepare();
//printf("%d\n",query(212));
//puts("\n");
//printf("%d\n",query(211));
//int N=1000000;
//for (int i=0;i<=N;i++)
//printf("%d\n",query(i));
int T;
read(T);
for (int i=1;i<=T;i++)
{
long long l,r;
read(l); read(r);
printf("%d\n",query(r)-query(l-1));
}
return 0;
}