URAL 1233 Amusing Numbers 好题

参照了nocow上的解法,照搬过来……

易知一个数X在数列中在另一个数Y前,当且仅当X前缀小于Y或前缀相等X短,那么我们分布考虑,比如对于数48561:

5位上:10000~48560;

4位上:1000~4856;

3位上:100~485;

2位上:10~48;

1位上:1~4.

这样我们就得到了1..N中48561的位置,可以用这个来判错.

接下来的方法类似,为了使得我们的N满足要求,我们必须去找比48561大且前缀比其小的数,同样有:

6位上:100000~485609;  //注意红色部分比原数减少了1,之前没注意这里一直WA……

……

---------------------以上nocow上给出的题解-----------------------

判断无解的情况:

1.当K != 10^x 时,假设到 K 时前面已经有的数的个数是cnt,如果 M - 1 < cnt 则无解。

2.当K == 10^x 时,K前面最多只有x个数,M - 1 > x 则无解。

一组数据:

1150 27350

12 2

20 13

3 23

3 3

100 3

输出:

1010679

0

20

29

3

100

 

#include <cstdio>

#include <cstring>

#include <cstdlib>



#define LL unsigned long long int



using namespace std;



const int MAXN = 30;



LL K, M, cnt;

LL bit[MAXN];

char strK[MAXN], strM[MAXN];

bool ok, find;



void init()

{

    bit[0] = 1;

    for ( int i = 1; i < MAXN; ++i )

        bit[i] = bit[i - 1] * (LL)10;

    return;

}



void chuli()

{

    cnt = 0;

    int len = strlen( strK );

    for ( int i = 1; i <= len; ++i )

    {

        //printf( "###%I64u %I64u\n", K / bit[ len - i ], bit[i - 1] );

        cnt += K / bit[ len - i ] - bit[i - 1] + 1;

    }

    --cnt;

    //printf("**%I64u %I64u\n", cnt, M );

    if ( cnt > M - 1 ) ok = false;

    return;

}



LL GetAns()

{

    LL cur = K;



    if ( cnt == M - 1 ) return cur;

    --cur;



    int i;

    for ( i = strlen(strK); ; ++i )

    {

        cur = cur * 10 + 9;

        //printf( "~~~%20I64u %20I64u\n", cur, bit[i] );

        LL tmp = cnt + cur - bit[i] + 1;

        //printf( "tmp=%I64d\n", tmp );

        if ( tmp == M - 1 ) return cur;

        if ( tmp >= M ) break;

        cnt = tmp;

    }



    return bit[i] + M - 1 - cnt - 1;

}



bool SpecialJudge()

{

    int len = strlen(strK);

    find = false;

    for ( int i = 0; i <= len; ++i )

    {

        if ( K == bit[i] )

        {

            find = true;

            break;

        }

    }

    if ( !find ) return true;

    if ( M - 1 > cnt ) return false;

    return true;

}



int main()

{

    //freopen( "out.txt", "r", stdin );

    //freopen( "s1.txt", "w", stdout );

    init();

    while ( scanf( "%s", strK ) == 1 )

    {

        scanf( "%I64u", &M );

        sscanf( strK, "%I64u", &K );



        ok = true;

        LL ans;

        chuli();



        if ( !SpecialJudge() )

        {

            puts("0");

            continue;

        }

        if ( find )

        {

            if ( cnt == M - 1 ) printf( "%I64u\n", K );

            else puts("0");

            continue;

        }



        if ( ok ) ans = GetAns();

        if ( ok ) printf( "%I64u\n", ans );

        else puts("0");

    }

    return 0;

}

 

你可能感兴趣的:(number)