題解/算法 {10034. 统计强大整数的数目}

題解/算法 {10034. 统计强大整数的数目}

@LINK: https://leetcode.cn/problems/count-the-number-of-powerful-integers/;

Suf: 題目給定的後綴字符串
這題非常考驗你對數位DP的理解裡, 分析數位DP的定義:
+: DP[i][j]: [i 0...0, i 9...9] 這個區間裡的合法字符串個數, 也就是 形如... Suf的個數; (注意 我們不關注Suf的後綴 關注的是他整個字符串, 也就是Suf=123, ?123是答案, 但423不是, 你可能認為 不考慮Suf後綴 那麼DP轉換可以進行嗎? 可以的, DP轉移 不會藉助DP[pre]的值 她是直接求的 當j>=Suf.size() 那麼DP = (Limit+1) ^ (j - Suf.size()) 注意不是10^?;
+: Get_alignedCount( pre, power) 即形如[pre 0...0, pre m...m] (m=Radix-1)這些數的答案:
. @IF(power >= Suf.size()): 那麼答案是DP[pre.back()][ power];
. @ELSE: 此時比如[?12 ??], Suf="1234", 我們統一把power給去掉, 然後比較12 == "12":

using __CountType_ = int64_t; // 个数的类型
static constexpr int __Radix_ = 10; // 进制
static constexpr int __MaxLength_ = 16; // 数字的最大长度
__CountType_ DP[ __Radix_ + 1][ __MaxLength_]; // `DP[i][j]`: `[i 0...0, i m...m] (m=Radix-1)`這些*字符串數*對答案的貢獻;

void Initialize(){
    memset( DP, 0, sizeof( DP));
    for( int power = 0; power < __MaxLength_; ++power){
        for( int head = 0; head < __Radix_; ++head){
            auto & curDP = DP[ head][ power]; // `[head 0...0, head m...m] (m=Radix-1, `0...0`的長度是`power`)`這些*字符串數*對答案的貢獻;
            curDP = 0;

            if( power == 0){ // `head`這一個數 對答案的貢獻;
                if( head > Limit){ continue;}
                if( 1==Suf.size() && head==(Suf.front()-'0')){ curDP = 1;} // 注意不是`head>=`
            }
            else{
                if( head > Limit){ continue;}
                if( power+1 == (int)Suf.size()){
                    if( head == (Suf.front()-'0')){ curDP = 1;}
                }
                else if( power+1 > (int)Suf.size()){
                    curDP += Integer::GetPower( Limit+1, power - (int)Suf.size()); // 注意是`Limit+1`而不是`10`, 不可以`* (head+1)`;
                }
            }
        }
    }
}
__CountType_ __Get_alignedCount( const vector & _prefix, int _power){
//< `prefix.front()`是高位, `[prefix 0...0, prefix m...m] (`0...0`的長度是power, `m=Radix-1`)`這些數(輸入一定保證這些數是沒有*前導零*的)對答案的貢獻;

    if( *max_element( _prefix.begin(), _prefix.end()) > Limit){ return 0;}

    if( _power == 0){ // `prefix`這一個數對答案的貢獻;
        if( _prefix.size() >= Suf.size()){
            int n1 = _prefix.size()-1, n2 = Suf.size()-1;
            while( n2>=0){
                if( _prefix[n1] != (Suf[n2]-'0')){ return 0;}
                -- n1, -- n2;
            }
            return 1;
        }
        return 0;
    }

    __CountType_ ANS = 0;
    if( _power+1 >= (int)Suf.size()){
        ANS = DP[_prefix.back()][ _power];
    }
    else if( (int)_prefix.size()+_power < (int)Suf.size()){
        ANS = 0;
    }
    else{
        int n1 = _prefix.size()-1, n2 = (int)Suf.size()-_power-1;
        while( n2>=0){
            if( _prefix[n1] != (Suf[n2]-'0')){ return 0;} // 注意`Suf[n2]`必須要`-'0'`;
            -- n1, -- n2;
        }
        return 1;
    }
    return ANS;
}

你可能感兴趣的:(题解,算法)