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
", K / bit[ len - i ], bit[i - 1] );
        cnt += K / bit[ len - i ] - bit[i - 1] + 1;
    }
    --cnt;
    //printf("**%I64u %I64u
", 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
", cur, bit[i] );
        LL tmp = cnt + cur - bit[i] + 1;
        //printf( "tmp=%I64d
", 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
", K );
            else puts("0");
            continue;
        }

        if ( ok ) ans = GetAns();
        if ( ok ) printf( "%I64u
", ans );
        else puts("0");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/GBRgbr/p/3240074.html