4061 Magic Multiplication,思维,枚举,优化
PTA | 程序设计类实验辅助教学平台 (pintia.cn)
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 A=a1a2…an, where ai indicates the i-th digit in A, and the second integer be B=b1b2…bm, where bi indicates the i-th digit in B. We have A⊗B=i=1∑nj=1∑maibj=a1b1+a1b2+⋯+a1bm+a2b1+⋯+anbm Note that the result of aibj is considered to be a \textbf{string} (without leading zeros if aibj>0, or contains exactly one `0' if aibj=0), NOT a normal integer. Also, the sum here means \textbf{string concatenation}, NOT the normal addition operation.
For example, 23 ⊗ 45 = 8101215. Because 8=2×4, 10=2×5, 12=3×4 and 15=3×5.
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 A and B.
Input
There are multiple test cases. The first line of the input contains an integer $T$, indicating the number of test cases. For each test case:
The first line contains two positive integers n and m (1≤n,m≤2×105), where n indicates the length of A and m indicates the length of B. 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 C without leading zeros, indicating the result of A⊗B. The length of C is no more than 2×105.
It's guaranteed that the sum of lengths of C over all test cases will not exceed 2×106.
Output
For each test case output one line.
If there exist such A and B that A⊗B=C, output one line containing two integers A and B separated by one space. Note that A and B should be positive integers without leading zeros, the length of A should be exactly n, and the length of B should be exactly m.
If there are multiple valid answers, output the answer with the smallest A; If there are still more than one answer, output one of them with the smallest B.
If such A and B 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
代码长度限制
32 KB
时间限制
1000 ms
内存限制
64 MB
解析:枚举,优化
题目大意: A⊗B=i=1∑nj=1∑maibj=a1b1+a1b2+⋯+a1bm+a2b1+⋯+anbm
给你两个数 n,m,C
表示A和B的位数,C表示A⊗B
让你求出A和B
这代题目给的公式一眼看上去很可怕,但只要发现的这道题目的性质就很好解决了
观察所给公式我们会发现一个性质:
C 的长度为n*m,且每m个长度都是Ai*{B0……Bm};
这样我们就可以根据这性质来枚举出A和B了;
对与 A[0] 我们可以重 1 到 9 枚举一边,满足A0*{B0……Bm}等于C的前m个数这所名当前的A[0]有可能满足题意,再根据此A[0]推出所有B[i],这样剩下的A[i]我们就可以根据当前的B和C推出来了.
这里注意:每推出一个A[i],都要检验一边,应为当前的A[0]不一定满足题意,所以基于当前A[0]推出来的其他结构亦要检验一边,才能保证最终结果是正确的。
根据此思路将代码写出来即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;
typedef long long LL;
const int N = 2e5 + 5;
int n, m;
char str[N];
int A[N];
int B[N];
int pos;
int getB() {
int num = 0;
for (int i = 0; i < m; i++) {
num = str[pos++] - '0';
if (A[0] > num && num != 0)
num = num * 10 + str[pos++] - '0';
if (num % A[0] == 0) {
B[i] = num / A[0];
if (B[i] >= 10)
return 0;
}
else
return 0;
}
return 1;
}
int getA() {
int num = 0;
for (int i = 1; i < n; i++) {//这里的i从1开始
num = str[pos++] - '0';
if (B[0] > num && num != 0)
num = num * 10 + str[pos++] - '0';
if (num % B[0] == 0) {
A[i] = num/B[0];
if (A[i] >= 10)
return 0;
}
else
return 0;
for (int j = 1; j < m; j++) {
num = str[pos++] - '0';
if (A[i] > num && num != 0)
num = num * 10 + str[pos++] - '0';
if (A[i]*B[j]!=num)//这里不能写成if(num/B[j]!=A[i])或if(num/A[i]!=B[j]),因为0不能当除数
return 0;
}
}
return 1;
}
int solve() {
int len = strlen(str);
int one = str[0] - '0';
int two = str[1]-'0' + one * 10;
for (int i = 1; i < 10; i++) {
if (one % i == 0) {
A[0] = i;
pos = 0;
if (getB() && getA() && pos == len) {
return 1;
}
}
}
for (int i = 1; i <= 9; i++) {
if (two % i == 0) {
A[0] = i;
pos = 0;
if (getB() && getA() && pos == len) {
return 1;
}
}
}
return 0;
}
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
scanf("%s", str);
if (solve()) {
for (int i = 0; i < n; i++)printf("%d", A[i]);
printf(" ");
for (int i = 0; i < m; i++)printf("%d", B[i]);
printf("\n");
}
else {
cout << "Impossible" << endl;
}
}
return 0;
}