Multiplying Digits(Dp+map)

For every positive integer we may obtain a non-negative integer by multiplying its digits. This defines a functionf, e.g. f(38) = 24.

This function gets more interesting if we allow for other bases. In base 3, the number 80 is written as 2222, so:f3(80) = 16.

Picture by Mees de Vries

We want you to solve the reverse problem: given a base B and a number N, what is the smallest positive integer X such that fB(X) = N?

Input

The input consists of a single line containing two integers B and N, satisfying 2 < B ≤ 10000 and 0 < N < 263.

Output

Output the smallest positive integer solution X of the equatio

n fB(X) = N. If no such Xexists, output the word “impossible”. The input is carefully chosen such that X < 263holds (if X exists).

Sample Input 1

Sample Input 2

Sample Input 3

Sample Input 4

Sample Output 1

Sample Output 2

Sample Output 3

Sample Output 4

10 24

38

10 11

impossible

9 216

546

10000 5810859769934419200
5989840988999909996

思路:先求出N的所有因子,接下来是个类似于完全背包的问题:对于这些价值和体积都为自身的因子组成总体积为N的最小值为多少。由于因子间是不连续的,要用到map实现 map传送门 设mp[i][j]表示还有i没被分解时所得到的最小价值为j

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#define  ll long long
#define inf 0x3f3f3f3f
using namespace std;
map<ll,ll>mp;
map<ll,ll>:: reverse_iterator it;
int prim[1008611],ans[1008611];
unsigned ll maxc=1ull<<63;
int main(){
    ll n,b;
    mp.clear();
    scanf("%lld%lld",&b,&n);
    if(n==1){
        printf("1\n");
        return 0;
    }
    ll k=0,tmp=n;
    for(int i=2;i<b;i++){
        if(n%i==0){
            prim[k++]=i;
            while(tmp%i==0){
                tmp/=i;
            }
        }
    }
    if(tmp!=1){
        printf("impossible\n");
        return 0;
    }
    mp[n]=0;
    
    for(it=mp.rbegin();it!=mp.rend();it++){//自后往前更新,保证u大的在前面
        ll u=it->first;
        ll v=it->second;
        ll maxn=v%b;
        for(ll i=k-1;i>=0;i--){
            if(prim[i]<maxn)break;//由于是不降序列,遇到比上一位小的break
            if(((long double)v*b+prim[i])>maxc)continue;
            if(u%prim[i]!=0)continue;//防止爆long long
            ll x=u/prim[i];
            ll y=v*b+prim[i];
            if(!mp[x]||mp[x]>y)mp[x]=y;
        }
    }
    printf("%lld\n",mp[1]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/xiao_you_you/article/details/89321532