题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4061
题意:定义一个长度为 n 的序列 a1,a2,..,an 和长度为 m 的序列 b1,b2,..,bm 所构成的新序列 c 为 a1b1,a1b2,....,anbm,给出最终的序列和两个初始序列的长度,构造出字典序最小的初始序列。
题解:首先我们知道两个个位数相乘最多可以得到两位数,易知最终序列的第一个数字 c1 的构造一定有 a1 的参与,当 a1 <= c1 时或者 c1 == 0时,a1 * b1 必须为个位数;否则 a1 * b1 必须为两位数,容易证明其正确性。有了这个性质以后,可以通过枚举 a1 得到完整的 b 序列,然后通过 b 序列再得出 a 序列。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define ll long long 4 #define ull unsigned long long 5 #define mst(a,b) memset((a),(b),sizeof(a)) 6 #define mp(a,b) make_pair(a,b) 7 #define pi acos(-1) 8 #define pii pair<int,int> 9 #define pb push_back 10 const int INF = 0x3f3f3f3f; 11 const double eps = 1e-6; 12 const int MAXN = 2e5 + 10; 13 const int MAXM = 1e8 + 10; 14 const ll mod = 1e9 + 7; 15 16 int n,m,len; 17 char s[MAXN]; 18 int a[MAXN],b[MAXN],now[MAXN],pos; 19 bool flag; 20 21 bool geta() { 22 for(int i = 2; i <= n; i++) { 23 int num = s[++pos]; 24 if(b[1] > num && num != 0) num = num * 10 + s[++pos]; 25 if(num % b[1] || num / b[1] >= 10) return false; 26 a[i] = num / b[1]; 27 for(int j = 2; j <= m; j++) { 28 num = s[++pos]; 29 if(a[i] > num && num != 0) num = num * 10 + s[++pos]; 30 if(a[i] * b[j] != num) return false; 31 } 32 } 33 if(pos != len) return false; 34 return true; 35 } 36 37 bool getb() { 38 pos = 0; 39 for(int i = 1; i <= m; i++) { 40 int num = s[++pos]; 41 if(a[1] > num && num != 0) num = num * 10 + s[++pos]; 42 if(num % a[1] || num / a[1] >= 10) return false; 43 b[i] = num / a[1]; 44 } 45 return true; 46 } 47 48 int main() { 49 #ifdef local 50 freopen("data.txt", "r", stdin); 51 // freopen("data.txt", "w", stdout); 52 #endif 53 int t; 54 scanf("%d",&t); 55 while(t--) { 56 scanf("%d%d%s",&n,&m,s + 1); 57 len = strlen(s + 1); 58 for(int i = 1; i <= len; i++) s[i] = s[i] - '0'; 59 flag = false; 60 for(int i = 1; i <= 9; i++) { 61 if(s[1] % i == 0) { 62 a[1] = i; 63 if(getb() && geta()) { 64 flag = true; 65 break; 66 } 67 } 68 } 69 if(!flag) { 70 for(int i = 1; i <= 9; i++) { 71 if((s[1] * 10 + s[2]) % i == 0) { 72 a[1] = i; 73 if(getb() && geta()) { 74 flag = true; 75 break; 76 } 77 } 78 } 79 } 80 if(flag) { 81 for(int i = 1; i <= n; i++) printf("%d",a[i]); 82 printf(" "); 83 for(int i = 1; i <= m; i++) printf("%d",b[i]); 84 printf(" "); 85 } else puts("Impossible"); 86 } 87 return 0; 88 }