【ZOJ】4061-Magic Multiplication 思维+模拟

题目链接

题意

定义\(A \otimes B = \sum\limits_{i=1}^n\sum\limits_{j=1}^m a_ib_j = a_1b_1 + a_1b_2 + \dots + a_1b_m + a_2b_1 + \dots + a_nb_m\)

现在给出 \(A\)\(B\) 的位数以及 \(A \otimes B\),输出 \(A\) 的值以及 \(B\) 的值,如果有多个答案,优先输出 \(A\) 的最小值。

思路

比赛的时候自己被自己迷惑住了。
队友说枚举 \(A_1\) ,就可以求出唯一一个 \(A_1\) 对应的 \(B\),我一直不信,因为主观认为对于 \(A_1\) 无法从给出的 \(A \otimes B\) 看出对应的 \(A_1 \times B_i\) 是一位还是两位,所以可能对于一个 \(A_1\) 可能求出很多个 \(B\)

但是后来仔细一想,对于一个 \(A_1\) 只可能有一个 \(B\)

当时时间不是很多了,中间浪费了一段时间,没有写完。

赛后补了。

首先枚举 \(A_1\) 的值 [1,9],然后我们遍历 \(A \otimes B\) ,先用 1 位除 \(A_1\),如果一位不行,就用两位,如果两位都不行,那么这个\(A_1\)就不合适。

直到得到 \(m\) 个数字,即 \(B\)

这时再用剩下的 \(A \otimes B\) "除" \(B\),和上面步骤类似,验证得到的 \(A\) 是否合法,如果合法,存起来这对 \(A,B\),排个序,输出最小的。

代码

/*
 * @Autor: valk
 * @Date: 2020-08-21 11:06:28
 * @LastEditTime: 2020-10-12 10:15:27
 * @Description: 如果邪恶  是华丽残酷的乐章 它的终场 我会亲手写上 晨曦的光 风干最后一行忧伤 黑色的墨 染上安详
 */
#include <bits/stdc++.h>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int mod = 1e9 + 7;
const int seed = 12289;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;

int n, m;
char str[N];
vector<int> a, b;
struct node {
    char a[N], b[N];
} ans[100];
int tot;
bool cmp(node x, node y)
{
    if (strlen(x.a) == strlen(y.a))
        return strcmp(x.a, y.a) < 0;
    return strlen(x.a) < strlen(y.a);
}

void getb(int pos)
{
    if(b[0]==0)
        return;
    int len = strlen(str + 1);
    for (int i = 1; i < n; i++) {
        vector<int> temp;
        for (int j = 0; j < m; j++) {
            if (pos > len) {
                return;
            }
            int now = str[pos] - '0';
            if (b[j] == 0) {
                if (now)
                    return;
                ++pos;
            } else {
                if (now % b[j] == 0 && now / b[j] < 10) {
                    temp.pb(now / b[j]);
                    ++pos;
                } else {
                    if (pos == len)
                        return;
                    now = now * 10 + str[pos + 1] - '0';
                    if (now % b[j] == 0 && now / b[j] < 10) {
                        temp.pb(now / b[j]);
                        pos += 2;
                    } else
                        return;
                }
            }
        }
        sort(temp.begin(), temp.end());
        temp.erase(unique(temp.begin(), temp.end()), temp.end());
        if (temp.size() == 0)
            temp.pb(0);
        if (temp.size() == 1) {
            a.pb(temp[0]);
        } else {
            return;
        }
    }
    if (pos != len + 1||a.size()!=n)
        return;
    tot++;
    for(int i=0;i<n;i++){
        ans[tot].a[i] = a[i] + '0';
    }
    ans[tot].a[n] = '\0';
    for (int i = 0; i < m;i++){
        ans[tot].b[i] = b[i] + '0';
    }
    ans[tot].b[m] = '\0';
}

void enumer()
{
    for (int i = 1; i < 10; i++) {
        a.clear(), b.clear();
        a.pb(i);
        int pos = 1;
        for (int j = 1; j <= m; j++) {
            int now = str[pos] - '0';
            if (now % i == 0 && now / i < 10) {
                b.pb(now / i);
                pos += 1;
            } else {
                now = now * 10 + str[pos + 1] - '0';
                if (now % i == 0 && now / i < 10) {
                    b.pb(now / i);
                    pos += 2;
                } else {
                    break;
                }
            }
        }
        if (b.size() == m) {
            getb(pos);
        }
    }
}

int main()
{
    int T;
    scanf("%d", &T);
    while (T--) {
        tot = 0;
        scanf("%d%d%s", &n, &m, str + 1);
        enumer();
        if(tot==0){
            printf("Impossible\n");
        }else{
            sort(ans + 1, ans + 1 + tot, cmp);
            printf("%s %s\n", ans[1].a, ans[1].b);
        }
    }
    return 0;
}
posted @ 2020-10-12 16:21  Valk3  阅读(100)  评论(0编辑  收藏  举报