题目链接: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;
}