ZOJ-4061 Magic Multiplication 2018年青島區域賽現場賽D題(思維 + 暴力構造)
阿新 • • 發佈:2018-12-19
題目連結:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4061
題目大意:題目定義一個運算子對於數A和數B的運演算法則為
, 表示數A的第 i 位數,表示數B的第 j 位數,現在令字串,這裡的加法為字串連線的相加。
比如,最後的結果由各位運算的結果連線起來得到。
現在給出最終的結果串C,以及A的長度n和B的長度m,要你求出原來的A序列和B序列。
題目思路:由於最終串是由n*m組一位數相乘得到的結果連線而成的,我們可以很容易知道一位數和一位數相乘最多得到一個兩位數,而且對於一個一位數a,如果另一個一位數 b 滿足 b % a == 0,那麼就一定不存在一個一位數 x 使得(b*10 + x) % a == 0。
所以 在將最終結果串拆開來的時候,對於乘積為時, 只會有唯一的 與之對應。
因此我們就可以考慮對的值進行列舉,先將結果串分解,將滿足當前值的B陣列的值求出來。接著再用求出來的B陣列將的值求出來,再對正確性進行驗證即可。
由於的取值只有可能是1~9,所以這個解法的時間複雜度為。
具體實現看程式碼:
#include <bits/stdc++.h> #define fi first #define se second #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define pb push_back #define MP make_pair #define lowbit(x) x&-x #define clr(a) memset(a,0,sizeof(a)) #define _INF(a) memset(a,0x3f,sizeof(a)) #define FIN freopen("in.txt","r",stdin) #define FOUT freopen("out.txt","w",stdout) #define IOS ios::sync_with_stdio(false) #define fuck(x) cout<<"["<<#x<<" "<<(x)<<"]"<<endl using namespace std; typedef long long ll; typedef unsigned long long ull; const int MX = 2e5 + 50; int n, m, _; char s[MX]; int a[MX], b[MX], c[MX]; int main() { // FIN; for (scanf("%d", &_); _; _--) { scanf("%d%d", &n, &m); scanf("%s", s + 1); int len = strlen(s + 1); if (2ll * n * m < len || len < 1ll * n * m) { puts("Impossible"); continue; } bool ok = 1; for (int i = 1; i <= len; i++) c[i] = s[i] - '0'; for (int i = 1; i <= 9; i++) { int now = 0, flag = 1, cnt = 0, pos = len + 1; for (int j = 1; j <= n; j++) a[j] = -1; for (int j = 1; j <= m; j++) b[j] = -1; for (int j = 1; j <= len; j++) { if (cnt == m) { pos = j; break; } now = c[j]; if (now % i == 0) b[++cnt] = now / i; else { if (j == len) { flag = 0; break; } now = now * 10 + c[j + 1]; j++; if (now % i != 0 || now / i >= 10) { flag = 0; break; } b[++cnt] = now / i; } } for (int j = 1; j <= m; j++) if (b[j] == -1) flag = 0; if (flag) { ok = 1; if (n == 1) { a[1] = i; if (pos <= len) ok = 0; } else { a[1] = i; int tmp = 2; cnt = 1; for (int j = pos; j <= len; j++) { if (cnt == m + 1) cnt = 1, tmp++; now = c[j]; if (b[cnt] == 0) { if (now != 0) { ok = 0; break; } cnt++; continue; } if (now % b[cnt] != 0) { if (j == len) { ok = 0; break; } now = now * 10 + c[j + 1]; j++; if (now % b[cnt] != 0 || now / b[cnt] >= 10) { ok = 0; break; } if (a[tmp] != -1) { if (a[tmp] != now / b[cnt]) { ok = 0; break; } } a[tmp] = now / b[cnt]; } else { if (a[tmp] != -1) { if (a[tmp] != now / b[cnt]) { ok = 0; break; } } a[tmp] = now / b[cnt]; } cnt++; } if (tmp != n || cnt != m + 1) ok = 0; } if (ok) { for (int j = 1; j <= n; j++) printf("%d", a[j]); printf(" "); for (int j = 1; j <= m; j++) printf("%d", b[j]); printf("\n"); break; } } } if (!ok) puts("Impossible"); } return 0; }