青岛……
没想到我大三了还会打铁
果然是太菜了
题意是两个数A,B上每一位相乘,然后顺次接在一起,现在给你结果C和原来两个数字的长度,要求恢复成原来的数字A,B。
两个个位数想乘,结果一定是小于等于两位的。我们首先能想到枚举A的第一个数字,然后用C恢复B,然后用B恢复A,中途判断能不能构成C就行。相当于每次搜都走一次C的长度,时间复杂度基本上是
O
(
9
l
e
n
c
)
O(9len_c)
O(9lenc)的,从数据上看不会超时。
如果暴力搜的话,会发现其实有很多取一位还是取两位的问题,我们要是能把这个地方优化掉,就不用回溯了。
我们列出99乘法表……会发现这样的规律:
两位数的乘积,第一位一定是小于这两个数的
这样就好办了,我们利用这个就能一次性判断这个位数了
#include <bits/stdc++.h>
#include <cstring>
#define ll long long
#define endl '\n'
using namespace std;
const int MAXN = 2e5 + 10;
char s[MAXN];
int a[MAXN],b[MAXN],c[MAXN];
int main()
{
// freopen("input.txt","w",stdout);
// data_gene(10000);
//freopen("input.txt","r",stdin);
int ca;
scanf("%d",&ca);
while(ca--)
{
int n,m;
scanf("%d %d",&n,&m);
scanf("%s",s);
int clen = strlen(s);
for(int i = 0; i<clen; ++i)
c[i] = s[i]-'0';
bool ok = 0;
for(int a1 = 1; a1 <= 9; ++a1)
{
int f = 1,p = 0;
for(int i = 1; i<=m; ++i)
{
int t1 = c[p];
if(t1 == 0)
{
p++;
b[i] = 0;
}
else if(t1 < a1)
{
t1 = t1 * 10 + c[p+1];
if(t1 % a1 != 0)
{
f = 0;
break;
}
b[i] = t1/a1;
p+=2;
}
else
{
if(t1 % a1 != 0)
{
f = 0;
break;
}
b[i] = t1/a1;
p++;
}
}
if(!f)
continue;
a[1] = a1;
for(int i = 2; i<=n; ++i)
{
int t1 = c[p];
int ta;
if(t1 == 0)
{
ta = 0;
p++;
}
else if(t1 < b[1])
{
t1 = t1*10 + c[p+1];
if(t1 % b[1] != 0)
{
f = 0;break;
}
p+=2;
ta = t1/b[1];
}
else
{
p++;
if(t1 % b[1] != 0)
{
f = 0;break;
}
ta = t1/b[1];
}
bool ff = 1;
for(int j = 2; j<=m; ++j)
{
int t2 = ta*b[j];
if(t2 == c[p])
{
p++;
}
else if(t2 == c[p]*10 + c[p+1])
p+=2;
else
{
ff = 0;
break;
}
}
if(ff)
a[i] = ta;
else
{
f = 0;
break;
}
}
if(!f)
continue;
if(p != clen)
continue;
ok = 1;
for(int i =1; i<=n; i++)
printf("%d",a[i]);
printf(" ");
for(int i = 1; i<=m; i++)
printf("%d",b[i]);
printf("\n");
break;
}
if(!ok)
puts("Impossible");
}
return 0;
}