版权声明:欢迎大家转载,转载请注明出处 https://blog.csdn.net/hao_zong_yin/article/details/83903909
题意:规则举例:1234*5678=5678101214161516212420242832,现在给出最终串,以及两个原串的长度,问两个原串是多少,设原串为A B,多解先令A尽量小,然后再令B尽量小
所有传的长度都在2e5以内,除非串只有一个0,否则没有前导0
思路:现场赛的时候拿到这个题一开始没什么思路放掉了,最后也没时间想了,赛后想一想其实暴搜就可以,因为匹配的概率本来就比较低,所以递归总次数也不会很多,当然需要一些技巧优化一下
首先可以明确的是确定了A的第一位,B也就确定了,以此为出发点进行暴搜,每次搜索枚举A的当前位,然后乘上B与C进行匹配,匹配成功继续递归,这样效率就挺高了,在此之上我发现两个串相乘(按题目中的定义)后的长度最小为len1*len2,最大为2*len1*len2,根据这一点可以在最小长度大于C的剩余长度或者最大长度小于C的剩余长度时剪枝,快10ms而已。。。弱剪枝
注意各种细节,判一下0什么的就做完了
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int T, N, M, L;
int cnt, pos;
char A[maxn], B[maxn], C[maxn];
bool getB(int x) {
cnt = 0;
pos = 0;
for (int i = 0; i < L; i++) {
int t = C[i] - '0';
if (x <= t || t == 0) {
if (t % x) return false;
else B[cnt++] = t / x + '0';
}
else {
if (i == L - 1) return false;
else {
i++;
t = t * 10 + C[i]-'0';
if (t % x) return false;
else B[cnt++] = t / x + '0';
}
}
if (cnt == M) {
B[M] = 0;
pos = i;
return true;
}
}
return false;
}
bool dfs(int a, int c) {
if (a == N && c == L) return true;
if (a == N || c >= L) return false;
// if (1LL*(N-a)*M > L-c || 2LL*(N-a)*M < L-c) return false;
for (int i = 0; i <= 9; i++) {
A[a] = i + '0';
int p = c;
bool ok = true;
for (int j = 0; j < M; j++) {
if (i * (B[j]-'0') < 10) {
if (i * (B[j]-'0') != C[p]-'0') {
ok = false;
break;
}
else p++;
}
else {
int d1 = i*(B[j]-'0')/10;
int d2 = i*(B[j]-'0')%10;
if (d1 == C[p]-'0' && p != L-1 && d2 == C[p+1]-'0') p += 2;
else {
ok = false;
break;
}
}
}
if (ok) {
if (dfs(a+1, p)) return true;
}
}
return false;
}
void solve() {
for (int i = 1; i <= 9; i++) {
if (getB(i)) {
A[0] = i + '0';
if (dfs(1, pos+1)) {
for (int j = 0; j < N; j++) printf("%c", A[j]);
printf(" ");
for (int j = 0; j < M; j++) printf("%c", B[j]);
printf("\n");
return;
}
}
}
printf("Impossible\n");
}
int main() {
scanf("%d", &T);
while (T--) {
scanf("%d%d", &N, &M);
getchar();
scanf("%s", C);
L = strlen(C);
if (L == 1 && C[0] == '0') {
if (N == 1 && M != 1) {
printf("0 1");
for (int i = 1; i < M; i++) printf("0");
printf("\n");
}
else if (N != 1 && M == 1) {
printf("1");
for (int i = 1; i < N; i++) printf("0");
printf(" 0\n");
}
else if (N == 1 && M == 1) {
printf("0 0\n");
}
else {
printf("Impossible\n");
}
}
else if (1LL*N*M > L || 2LL*N*M < L) {
printf("Impossible\n");
}
else {
solve();
}
}
return 0;
}