1. 程式人生 > >ACM-ICPC 2018 青島賽區現場賽 D. Magic Multiplication && ZOJ 4061 (思維+構造)

ACM-ICPC 2018 青島賽區現場賽 D. Magic Multiplication && ZOJ 4061 (思維+構造)

題目連結: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("\n"); 85 } else puts("Impossible"); 86 } 87 return 0; 88 }