2020杭电多校第六场 Fragrant numbers(区间DP)

Problem Description
Many people love numbers, and some have a penchant for specific numbers. Nowadays in popular culture, 1145141919 is a very fragrant number, and many people want to represent all other numbers with this number.

Let S be an infinite string of “1145141919” infinitely stitched together as “114514191911451419191145141919…”.

Take a prefix T of S , you can insert ‘(’ , ‘)’ , ‘+’ or ‘∗’ to T to form a new string T′, and then let the value of T′ be val(T′) according to ordinary rules. (You can insert any number of operators, even 0. But need to ensure that the inserted operators form legitimate operations)

Now for a number N, please calculate the minimum length of T that can make val(T′)=N. For example, when N=520, the minimum length of 6 (pick the first 6 characters 114514 and insert operators to make T′=1+1+4+514 , then we have val(T′)=520 )

If no such T exists, output −1.

Input
There are multiple test cases.

The first line with a number t indicates the number of test cases.

For each test case, one integer N per line indicates an inquiry.

1≤t≤30

1≤N≤5000

Output
Output t lines.

One integer per line indicates the corresponding answer.

Sample Input
3
520
1
2

Sample Output
6
1
2

Source
2020 Multi-University Training Contest 6

题意:
1145141919开头的循环串,可以去一个前缀在字符间加+,*,(,)。求一个值至少多长前缀可以表示。

思路:
只想到爆搜,正解是区间DP。
维护 f [ i ] [ j ] f[i][j] 代表区间 [ i , j ] [i,j] 可以表示哪些数,用vector存。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <stack>
#include <vector>
#include <set>

using namespace std;

typedef long long ll;
const int maxn = 5005;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;

char s[30] = "011451419191145141919";
int ans[maxn];
int vis[16][16][5005];
vector<int>f[16][16];

ll get(int l,int r) {
    ll tmp = 0;
    for(int i = l;i <= r;i++) {
        tmp = tmp * 10 + s[i] - '0';
    }
    return tmp;
}

void init() {
    for(int i = 1;i <= 15;i++) {
        for(int j = i;j <= 15;j++) {
            ll num = get(i,j);
            if(num <= 5000) {
                f[i][j].push_back(num);
                vis[i][j][num] = 1;
            }
        }
    }
}

int main() {
    init();
    for(int l = 1;l <= 15;l++) { //长度
        for(int i = 1;i + l - 1 <= 15;i++) { //起点
            int j = i + l - 1;
            for(int k = i;k < j;k++) {
                for(int it1 = 0;it1 < f[i][k].size();it1++) {
                    for(int it2 = 0;it2 < f[k + 1][j].size();it2++) {
                        int num1 = f[i][k][it1],num2 = f[k + 1][j][it2];
                        if(num1 + num2 <= 5000 && !vis[i][j][num1 + num2]) {
                            f[i][j].push_back(num1 + num2);
                            vis[i][j][num1 + num2] = 1;
                        }
                        if(num1 * num2 <= 5000 && !vis[i][j][num1 * num2]) {
                            f[i][j].push_back(num1 * num2);
                            vis[i][j][num1 * num2] = 1;
                        }
                    }
                }
            }
        }
    }
    
    memset(ans,0x3f,sizeof(ans));
    for(int i = 1;i <= 15;i++) {
        for(auto it = f[1][i].begin();it != f[1][i].end();it++) {
            int num = *it;
            if(num <= 5000) ans[num] = min(ans[num],i);
        }
    }
    
//    for(int i = 1;i <= 5000;i++) {
//        printf("%d ",ans[i]);
//    }
    int T;scanf("%d",&T);
    while(T--) {
        int n;scanf("%d",&n);
        if(ans[n] == INF) printf("-1\n");
        else printf("%d\n",ans[n]);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/tomjobs/article/details/107853174
今日推荐