題目鏈接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4061
題目大意:題目定義一個運算符對於數A和數B的運算法則爲
, 表示數A的第 i 位數,表示數B的第 j 位數,現在令字符串,這裏的加法爲字符串連接的相加。
比如,最後的結果由各位運算的結果連接起來得到。
現在給出最終的結果串C,以及A的長度n和B的長度m,要你求出原來的A序列和B序列。
題目思路:由於最終串是由n*m組一位數相乘得到的結果連接而成的,我們可以很容易知道一位數和一位數相乘最多得到一個兩位數,而且對於一個一位數a,如果另一個一位數 b 滿足 b % a == 0,那麼就一定不存在一個一位數 x 使得(b*10 + x) % a == 0。
所以 在將最終結果串拆開來的時候,對於乘積爲時, 只會有唯一的 與之對應。
因此我們就可以考慮對的值進行枚舉,先將結果串分解,將滿足當前值的B數組的值求出來。接着再用求出來的B數組將的值求出來,再對正確性進行驗證即可。
由於的取值只有可能是1~9,所以這個解法的時間複雜度爲。
具體實現看代碼:
#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define pb push_back
#define MP make_pair
#define lowbit(x) x&-x
#define clr(a) memset(a,0,sizeof(a))
#define _INF(a) memset(a,0x3f,sizeof(a))
#define FIN freopen("in.txt","r",stdin)
#define FOUT freopen("out.txt","w",stdout)
#define IOS ios::sync_with_stdio(false)
#define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int MX = 2e5 + 50;
int n, m, _;
char s[MX];
int a[MX], b[MX], c[MX];
int main() {
// FIN;
for (scanf("%d", &_); _; _--) {
scanf("%d%d", &n, &m);
scanf("%s", s + 1);
int len = strlen(s + 1);
if (2ll * n * m < len || len < 1ll * n * m) {
puts("Impossible");
continue;
}
bool ok = 1;
for (int i = 1; i <= len; i++) c[i] = s[i] - '0';
for (int i = 1; i <= 9; i++) {
int now = 0, flag = 1, cnt = 0, pos = len + 1;
for (int j = 1; j <= n; j++) a[j] = -1;
for (int j = 1; j <= m; j++) b[j] = -1;
for (int j = 1; j <= len; j++) {
if (cnt == m) {
pos = j;
break;
}
now = c[j];
if (now % i == 0) b[++cnt] = now / i;
else {
if (j == len) {
flag = 0;
break;
}
now = now * 10 + c[j + 1]; j++;
if (now % i != 0 || now / i >= 10) {
flag = 0;
break;
}
b[++cnt] = now / i;
}
}
for (int j = 1; j <= m; j++) if (b[j] == -1) flag = 0;
if (flag) {
ok = 1;
if (n == 1) {
a[1] = i;
if (pos <= len) ok = 0;
} else {
a[1] = i;
int tmp = 2;
cnt = 1;
for (int j = pos; j <= len; j++) {
if (cnt == m + 1) cnt = 1, tmp++;
now = c[j];
if (b[cnt] == 0) {
if (now != 0) {
ok = 0;
break;
}
cnt++;
continue;
}
if (now % b[cnt] != 0) {
if (j == len) {
ok = 0;
break;
}
now = now * 10 + c[j + 1]; j++;
if (now % b[cnt] != 0 || now / b[cnt] >= 10) {
ok = 0;
break;
}
if (a[tmp] != -1) {
if (a[tmp] != now / b[cnt]) {
ok = 0;
break;
}
}
a[tmp] = now / b[cnt];
} else {
if (a[tmp] != -1) {
if (a[tmp] != now / b[cnt]) {
ok = 0;
break;
}
}
a[tmp] = now / b[cnt];
}
cnt++;
}
if (tmp != n || cnt != m + 1) ok = 0;
}
if (ok) {
for (int j = 1; j <= n; j++) printf("%d", a[j]);
printf(" ");
for (int j = 1; j <= m; j++) printf("%d", b[j]);
printf("\n");
break;
}
}
}
if (!ok) puts("Impossible");
}
return 0;
}