Hdu 5676 ztr loves lucky numbers

定义幸运数字为十进制表示下只有 4 7 ,并且 4 7 的个数一样多的数。

求不小于 n 的最小幸运数字 n1018

(这是我称为数位贪心的一个题

首先显然的是一个幸运数字的位数一定是偶数

所以如果给出的 n 的位数是奇数的话,可以直接构造一个 444...777 作为答案

如果是偶数的话

依然是从高位到低位考虑

记录当前的位置 pos ,剩下的 4 的个数,剩下的 7 的个数,是否卡到下界 bnd

这样根据 n 在当前位的那个数,可以找到状态之间的转移

值得注意的是在当前位放下 4 之后如果返回的值为 false ,即后面没有合法的情况,则还需要尝试放下 7 ,如果放下 7 之后后面没有合法的情况,则直接返回 false 即可

另外在放下 4 或者 7 的时候要注意 4 或者 7 的个数是不是足够

我是代码的昏割线

#include<cstdio>
using namespace std;

#define LL long long

int arr[30];
int anser[30];

void outans(int len){
    for(int i=0;i<len/2;i++){
        printf("4");
    }
    for(int i=0;i<len/2;i++){
        printf("7");
    }
}

int lenth(LL v){
    int ret = 0;
    while(v){
        arr[ret++] = v % 10;
        v /= 10;
    }
    return ret;
}

bool ans(int pos,int ll,int lr,bool bnd){
    if(pos < 0)
        return true;
    if(!bnd){
        if(ll){
            anser[pos] = 4;
            return ans(pos-1,ll-1,lr,bnd);
        }
        else{
            anser[pos] = 7;
            return ans(pos-1,ll,lr-1,bnd);
        }
    }
    else{
        bool flag;
        if(arr[pos] < 4 && ll){
            anser[pos] = 4;
            return ans(pos-1,ll-1,lr,false);
        }
        if(arr[pos] == 4 && ll){
            anser[pos] = 4;
            flag = ans(pos-1,ll-1,lr,true);
            if(flag)
                return true;
        }
        if(lr==0)
            return false;
        if(arr[pos] < 7){
            anser[pos] = 7;
            return ans(pos-1,ll,lr-1,false);
        }
        if(arr[pos] == 7){
            anser[pos] = 7;
            return ans(pos-1,ll,lr-1,true);
        }
        return false;
    }
}

int main(){
    LL v;
    int T;
    scanf("%d",&T);
    while(T-- && ~scanf("%I64d",&v)){
        int len = lenth(v);
        if(v <= 0){
            puts("47");
            continue;
        }
        if(len % 2){
            outans(len+1);
            puts("");
        }
        else{
            if(ans(len-1,len / 2,len / 2,true)){
                for(int i=len-1;i>=0;i--){
                    printf("%d",anser[i]);
                }
            }
            else{
                outans(len+2);
            }
            puts("");
        }
    }
    return 0;
}

然而其实这个题只要把所有符合条件的幸运数都求出来,然后每次二分就好了

你可能感兴趣的:(Hdu 5676 ztr loves lucky numbers)