ZOJ 4061 Magic Multiplication——暴搜

版权声明:欢迎大家转载,转载请注明出处 https://blog.csdn.net/hao_zong_yin/article/details/83903909

题意:规则举例: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;
}

猜你喜欢

转载自blog.csdn.net/hao_zong_yin/article/details/83903909
ZOJ
今日推荐