1. 程式人生 > >ZOJ 4061 Magic Multiplication——暴搜

ZOJ 4061 Magic Multiplication——暴搜

題意:規則舉例:1234*5678=5678101214161516212420242832,現在給出最終串,以及兩個原串的長度,問兩個原串是多少,設原串為A B,多解先令A儘量小,然後再令B儘量小

所有傳的長度都在2e5以內,除非串只有一個0,否則沒有前導0

思路:現場賽的時候拿到這個題一開始沒什麼思路放掉了,最後也沒時間想了,賽後想一想其實暴搜就可以,因為匹配的概率本來就比較低,所以遞迴總次數也不會很多,當然需要一些技巧優化一下

首先可以明確的是確定了A的第一位,B也就確定了,以此為出發點進行暴搜,每次搜尋列舉A的當前位,然後乘上B與C進行匹配,匹配成功繼續遞迴,這樣效率就挺高了,在此之上我發現兩個串相乘(按題目中的定義)後的長度最小為len1*len2,最大為2*len1*len2,根據這一點可以在最小長度大於C的剩餘長度或者最大長度小於C的剩餘長度時剪枝,快10ms而已。。。弱剪枝

注意各種細節,判一下0什麼的就做完了

 

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int T, N, M, L;
int cnt, pos;
char A[maxn], B[maxn], C[maxn];
bool getB(int x) {
    cnt = 0;
    pos = 0;
    for (int i = 0; i < L; i++) {
        int t = C[i] - '0';
        if (x <= t || t == 0) {
            if (t % x) return false;
            else B[cnt++] = t / x + '0';
        }
        else {
            if (i == L - 1) return false;
            else {
                i++;
                t = t * 10 + C[i]-'0';
                if (t % x) return false;
                else B[cnt++] = t / x + '0';
            }
        }
        if (cnt == M) {
            B[M] = 0;
            pos = i;
            return true;
        }
    }
    return false;
}
bool dfs(int a, int c) {
    if (a == N && c == L) return true;
    if (a == N || c >= L) return false;
//    if (1LL*(N-a)*M > L-c || 2LL*(N-a)*M < L-c) return false;
    for (int i = 0; i <= 9; i++) {
        A[a] = i + '0';
        int p = c;
        bool ok = true;
        for (int j = 0; j < M; j++) {
            if (i * (B[j]-'0') < 10) {
                if (i * (B[j]-'0') != C[p]-'0') {
                    ok = false;
                    break;
                }
                else p++;
            }
            else {
                int d1 = i*(B[j]-'0')/10;
                int d2 = i*(B[j]-'0')%10;
                if (d1 == C[p]-'0' && p != L-1 && d2 == C[p+1]-'0') p += 2;
                else {
                    ok = false;
                    break;
                }
            }
        }
        if (ok) {
            if (dfs(a+1, p)) return true;
        }
    }
    return false;
}
void solve() {
    for (int i = 1; i <= 9; i++) {
        if (getB(i)) {
            A[0] = i + '0';
            if (dfs(1, pos+1)) {
                for (int j = 0; j < N; j++) printf("%c", A[j]);
                printf(" ");
                for (int j = 0; j < M; j++) printf("%c", B[j]);
                printf("\n");
                return;
            }
        }
    }
    printf("Impossible\n");
}
int main() {
    scanf("%d", &T);
    while (T--) {
        scanf("%d%d", &N, &M);
        getchar();
        scanf("%s", C);
        L = strlen(C);
        if (L == 1 && C[0] == '0') {
            if (N == 1 && M != 1) {
                printf("0 1");
                for (int i = 1; i < M; i++) printf("0");
                printf("\n");
            }
            else if (N != 1 && M == 1) {
                printf("1");
                for (int i = 1; i < N; i++) printf("0");
                printf(" 0\n");
            }
            else if (N == 1 && M == 1) {
                printf("0 0\n");
            }
            else {
                printf("Impossible\n");
            }
        }
        else if (1LL*N*M > L || 2LL*N*M < L) {
            printf("Impossible\n");
        }
        else {
            solve();
        }
    }
    return 0;
}