Codeforces Round #426 (Div. 2) E-Ever-Hungry Krakozyabra (爆搜)

来源:互联网 发布:哪些明星在淘宝开店 编辑:程序博客网 时间:2024/06/03 06:02

E. Ever-Hungry Krakozyabra

Recently, a wild Krakozyabra appeared at Jelly Castle. It is, truth to be said, always eager to have something for dinner.Its favorite meal is natural numbers (typically served with honey sauce), or, to be more precise, the zeros in their corresponding decimal representations. As for other digits, Krakozyabra dislikes them; moreover, they often cause it indigestion! So, as a necessary precaution, Krakozyabra prefers to sort the digits of a number in non-descending order before proceeding to feast. Then, the leading zeros of the resulting number are eaten and the remaining part is discarded as an inedible tail.For example, if Krakozyabra is to have the number 57040 for dinner, its inedible tail would be the number 457.Slastyona is not really fond of the idea of Krakozyabra living in her castle. Hovewer, her natural hospitality prevents her from leaving her guest without food. Slastyona has a range of natural numbers from L to R, which she is going to feed the guest with. Help her determine how many distinct inedible tails are going to be discarded by Krakozyabra by the end of the dinner.

Input

In the first and only string, the numbers L and R are given – the boundaries of the range (1 ≤ L ≤ R ≤ 10^18).

Output

Output the sole number – the answer for the problem.

Examples

input1 10output9input40 57output17input157 165output

题目大意

给定区间[L,R],求区间中的数去掉这个数中的0之后,把这个数各个数位上的数从小到大排列后,总共有多少个不同的排列情况。

此题看着很神,然而我们考虑一下发现,最多有18位,每个位置上只能是1-9,并且必须按顺序排列,因此只需要考虑1-9的末位放在哪里,也就是最多只有C918+9中可能组合,大概是4686824种。
因此我们可以考虑暴搜,枚举每一种可能,然后检验是否可以通过增加一些0的方式来使得当前的数被放到[L,R]区间中。

那么我们需要一个快速的验证。我们用B[x]表示当前数中数字x的个数,用L[i]和R[i]来表示L和R从高到低第i位的数字。那么,我们枚举L和R的每一位来讨论。

我们用(x,lf,rf)来表示枚举到第x位,lf表示当前构造出的数是否和L的1-x-1位完全相等,rf同理。
分三种情况
case 1. lf==1&&rf==1

这说明当前构造的数和L,R的前x-1位完全相等,那么我们令a=L[x],b=R[x]如果a==b,那么直接进入(x+1,lf,rf)如果a<b&&在[a+1,b-1]内存在一个数c使得B[c]>0,那么我们只需要令当前位置等于c,那么后面位置可以随意排列,显然可行。如果a<b&&a和b之间不存在c满足上述条件,那么如果B[a]>0进入(x+1,1,0)和如果B[b]>0进入(x+1,0,1)。                    

case 2.lf==1&&rf==0

这说明当前无论填入什么数字,构造出的数一定小于R。同样令a=L[x]。如果在[a+1,9]内存在一个c使得B[c]>0,那么显然可行。否则如果B[a]>0进入(x+1,1,0)

case 3.lf==0&&rf==1

同case 2处理。

于是,观察复杂度可发现,复杂度大概和R的位数差不多,因为只有当lf==1&&rf==1使才会产生不同情况。而显然这个不同情况往下就是单链的搜索树。

于是总复杂度C9K+9K,K是R的位数。

代码:

#include<stdio.h>#include<iostream>#include<algorithm>#include<cstring>using namespace std;int L[20],R[20],B[10],A[10],ans,n;bool ok(int l,int r){    if(l>r)return 0;    for(int i=l;i<=r;i++)    if(B[i])return 1;    return 0;}bool judge(int x,int lf,int rf){    if(x>n)return 1;    int l=L[x],r=R[x];    if(lf&&rf)    {        if(l==r)        {            if(B[l])            {                B[l]--;                if(judge(x+1,1,1))return 1;                B[l]++;            }            return 0;        }        if(ok(l+1,r-1))return 1;        if(B[l])        {            B[l]--;            if(judge(x+1,1,0))return 1;            B[l]++;        }        if(B[r])        {            B[r]--;            if(judge(x+1,0,1))return 1;            B[r]++;        }        return 0;    }    else if(lf)    {        if(ok(l+1,9))return 1;        if(B[l])        {            B[l]--;            if(judge(x+1,1,0))return 1;            B[l]++;        }        return 0;    }    else if(rf)    {        if(ok(0,r-1))return 1;        if(B[r])        {            B[r]--;            if(judge(x+1,0,1))return 1;            B[r]++;        }        return 0;    }    return 0;}void Work(int x,int sum){    if(x==10)    {        memcpy(B,A,sizeof(A));        B[0]+=sum;        if(judge(1,1,1))ans++;        return;    }    for(int i=0;i<=sum;i++)    {        A[x]=i;        Work(x+1,sum-i);    }}int main(){    int i;    long long x,y,t;    cin>>x>>y;t=y;    while(t){t/=10;n++;}    for(i=n;i>=1;i--)R[i]=y%10,y/=10;    for(i=n;i>=1;i--)L[i]=x%10,x/=10;    Work(1,n);    cout<<ans;}
阅读全文
1 0
原创粉丝点击