E - Digit Products 实在是瞎搞

首先我是想把题目分成好几部分来做 首先是第一部分 列如88897 我们找到它的最高位 然后先把10000以下的算出来 如何去算呢 分成两部分 一部分是 没有0的 一部分是有0的 有0这一部分用dp + map就可以了因为 最多组成的乘积有 9^9 / 9! 为1000多一点 所以开map是完全没问题的 没有0的部分用容斥的思想 就是全部数减掉 每位都>=1 的情况
因为我们这个是只能在整数部分 就是后面每位都可以取到9的情况 我们不妨从前往后 把每一位的小一位取出来 去求 数量 最后统计一下即可

#include<iostream>
#include<unordered_map>

using namespace std;

typedef long long ll;

const int N = 1e5 + 10;

unordered_map<ll,ll>mp[25];

ll b[N];

ll qpow(ll a,ll b){
    
    
    ll s = 1;
    while(b){
    
    
        if(b & 1) s = s * a;
        a = a * a;
        b >>= 1;
    }
    return s;
}

int main(){
    
    
    ll n,m;
    cin >> n >> m;

    ll s = n,dig = 0;
    while(s){
    
    
        s /= 10;
        dig++;
    }

    ll sum = 0,cnt = 0;
    for(ll i = 1; i <= 9; i++){
    
    
        if(!mp[1][i] && i <= m){
    
    
            b[++cnt] = i;
            mp[1][i] = 1;
            sum += 1;
        }
    }

    for(ll i = 2; i <= dig - 1; i++){
    
    
        ll sb = cnt;
        for(ll j = 1; j <= sb; j++){
    
    
            for(ll k = 1; k <= 9; k++){
    
    
                if(!mp[i - 1][b[j] * k] && !mp[i][b[j] * k]){
    
    
                    if(b[j] * k <= m){
    
    
                        sum += mp[i - 1][b[j]];
                        b[++cnt] = b[j] * k;
                        mp[i][b[j] * k] += mp[i - 1][b[j]];
                    }
                }else{
    
    
                    if(b[j] * k <= m){
    
    
                        mp[i][b[j] * k] += mp[i - 1][b[j]];
                        sum += mp[i - 1][b[j]];
                    }

                }
            }
            //cout << i << " " << b[j] << " " << mp[i][b[j]] <<endl;
        }
    }

    for(ll i = dig; i >= 2; i--){
    
    
        sum += 9 * qpow(10,i - 2) - qpow(9,i - 1);
        //cout << i - 1 << " " << 9 * qpow(10,i - 2) - qpow(9,i - 1)  << "Asd" <<endl;
    }

    /*cout <<sum << endl;
    for(int i = 1; i <= cnt; i++){
        cout <<b[i] << ' ' << mp[1][b[i]] << endl;
    }*/
    mp[0][1] = 1;
    s = 1;
    for(ll i = dig; i >= 1; i--){
    
    
        //cout << sum << endl;
        if(s == 0){
    
    
            sum += n % qpow(10,i);
            break;
            return 0;
        }
        for(ll j = ((n / qpow(10,i - 1)) % 10) - 1; j >= 1; j--){
    
    
            for(ll k = 1; k <= cnt; k++){
    
    
                if(b[k] * s * j <= m){
    
    
                        //cout << i << " " << j << " " << b[k] <<" " << mp[i - 1][b[k]] << "ASDA" << endl;
                    sum += mp[i - 1][b[k]];
                }
            }
        }
        if(i != dig && ((n / qpow(10,i - 1)) % 10) >= 1) sum += (((n / qpow(10,i - 1)) % 10)) * qpow(10,i - 1) - (((n / qpow(10,i - 1)) % 10) - 1) * qpow(9,i - 1);
        if(i == dig && ((n / qpow(10,i - 1)) % 10) >= 2) sum += (((n / qpow(10,i - 1)) % 10) - 1) * qpow(10,i - 1) - (((n / qpow(10,i - 1)) % 10) - 1) * qpow(9,i - 1);
        //cout <<sum << "TTT" <<endl;
        s *= ((n / qpow(10,i - 1)) % 10);
       // cout <<s <<"GG"<< endl;
     }

    if(s <= m) sum++;
    cout << sum << endl;

    /*int ss = 0;
    for(int i = 1; i <= n; i++){
        int s = i,g = 1;
        while(s){
            g *= s % 10;
            s /= 10;
        }
        if(g <= m) ss++;

    }
    cout << ss << "Asd" << endl;*/





    return 0;
}

猜你喜欢

转载自blog.csdn.net/qqqingyi/article/details/118500841