D - Magic Multiplication(The 2018 ACM-ICPC Asia Qingdao Regional Contest)(找規律+構造)
Time limit:1000 ms
Memory limit:65536 kB
judge:
ZOJ 4061
vjudge
Description
BaoBao is now learning a new binary operation between two positive integers, represented by , in his magic book. The book tells him that the result of such operation is calculated by concatenating all multiple results of each digit in the two integers.
Formally speaking, let the first integer be , where indicates the -th digit in , and the second integer be , where indicates the -th digit in . We have Note that the result of is considered to be a \textbf{string} (without leading zeros if , or contains exactly one `0’ if ), NOT a normal integer. Also, the sum here means \textbf{string concatenation}, NOT the normal addition operation.
For example, 23 45 = 8101215. Because , , and .
BaoBao is very smart and soon knows how to do the inverse operation of . Now he gives you the result of a operation and the numbers of digits in the two original integers. Please help him to restore the two original integers and .
Input
There are multiple test cases. The first line of the input contains an integer , indicating the number of test cases. For each test case:
The first line contains two positive integers and (), where indicates the length of and indicates the length of . Here length of an integer means the length of the string when writing the number in decimal notation without leading zeros.
The second line contains only one positive integer without leading zeros, indicating the result of . The length of is no more than .
It’s guaranteed that the sum of lengths of over all test cases will not exceed .
Output
For each test case output one line.
If there exist such and that , output one line containing two integers and separated by one space. Note that and should be positive integers without leading zeros, the length of should be exactly , and the length of should be exactly .
If there are multiple valid answers, output the answer with the smallest ; If there are still more than one answer, output one of them with the smallest .
If such and do not exist, print “Impossible” (without quotes) on a single line.
Sample Input
4
2 2
8101215
3 4
100000001000
2 2
80101215
3 4
1000000010000
Sample Output
23 45
101 1000
Impossible
Impossible
題意
這裏又三個數字:。給你 和 的長度和 ,問你是否能還原出 和 ,如果能就輸出 和 。
有如下運算:
例:23 45 = 8101215. Because , , and 。
題解
難點在於我們在枚舉 時無法確定該取一位數字還是兩位數字。
但我們知道,兩個長度爲 的數字相乘,其最小值是 ,最大值是 ,即乘積的長度不超過 。其次,若乘積的長度是 ,則乘積的十位數字小於兩個數字的任意一個;如果乘積的長度是 ,則乘積大於兩個數字的任意一個。
所以我們在枚舉數字時,只需要判斷一下 的數字和我們枚舉的數字的大小就可知道該取 位還是該取兩位:如果 的數字小於枚舉數字,就取兩位,然後判斷是否能整除;如果 的數字小於枚舉數字,就取 位,然後判斷是否能整除。
因爲 和 的長度是已知的,所以我們可以先枚舉 ,然後利用 的前半部分和 枚舉 (一個 對應 個或 個 ),然後再利用枚舉的 去推導剩餘的 。如果推導成功就得出了答案,而且因爲推導的過程是由大到小的,所以第一個滿足要求的答案就是最小的答案。
代碼
#include <bits/stdc++.h>
#define maxn 200005
#define _for(i, a) for(int i = 0; i < (a); ++i)
#define _rep(i, a, b) for(int i = (a); i <= (b); ++i)
#define scl(x) scanf("%lld", &x)
#define sc(x) scanf("%d", &x)
using namespace std;
int T, n, m;
int a[maxn], b[maxn];
char c[maxn];
bool getb() {
int len = strlen(c), pos = 0;
_for(i, m) {
if (pos == len) return 0; //C不夠用了
int x = c[pos++] - '0';
if (pos < len && x && x < a[0]) x = x * 10 + c[pos++] - '0';
if (x % a[0] || x / a[0] > 9) return 0; //除不盡或者商是兩位數
b[i] = x / a[0];
}
_rep(i, 1, n - 1) {
_for(j, m) {
if (pos == len) return 0; //C不夠用了
int x = c[pos++] - '0';
if (pos < len && x && x < b[j]) x = x * 10 + c[pos++] - '0';
if (x && (b[j] == 0 || j && a[i] == 0)) return 0; //a和b都爲0但c不爲0
if (x == 0) {
if (j && a[i] && b[j]) return 0; //c爲0但a和b都不爲0;j不爲0代表a已經被賦值
if (!j) a[i] = 0;
}
else {
if (x % b[j] || j && x / b[j] != a[i] || x / b[j] > 9) return 0; //除不盡或者商是兩位數
a[i] = x / b[j];
}
}
}
return pos == len;
}
bool sol() {
sc(n), sc(m);
scanf("%s", c);
int x = c[0] - '0';
_rep(i, 1, 9) { //利用a[0]找出b
if (x % i == 0) {
a[0] = i;
if (getb()) return 1;
}
}
x = x * 10 + c[1] - '0';
_rep(i, 1, 9) { //利用b找出a
if (x % i == 0) {
a[0] = i;
if (getb()) return 1;
}
}
return 0;
}
int main() {
while (cin >> T) {
_for(i, T) {
if (sol()) {
_for(j, n) printf("%d", a[j]);
printf(" ");
_for(j, m) printf("%d", b[j]);
printf("\n");
}
else printf("Impossible\n");
}
}
return 0;
}