1. 程式人生 > >4061 Magic Multiplication (直接模擬)

4061 Magic Multiplication (直接模擬)

青島…… 沒想到我大三了還會打鐵 果然是太菜了

題意是兩個數A,B上每一位相乘,然後順次接在一起,現在給你結果C和原來兩個數字的長度,要求恢復成原來的數字A,B。

兩個個位數想乘,結果一定是小於等於兩位的。我們首先能想到列舉A的第一個數字,然後用C恢復B,然後用B恢復A,中途判斷能不能構成C就行。相當於每次搜都走一次C的長度,時間複雜度基本上是O(9lenc)O(9len_c)的,從資料上看不會超時。 如果暴力搜的話,會發現其實有很多取一位還是取兩位的問題,我們要是能把這個地方優化掉,就不用回溯了。 我們列出99乘法表……會發現這樣的規律: 兩位數的乘積,第一位一定是小於這兩個數的 這樣就好辦了,我們利用這個就能一次性判斷這個位數了

#include <bits/stdc++.h>
#include <cstring>
#define ll long long
#define endl '\n'
using namespace std;
const int MAXN = 2e5 + 10;
char s[MAXN];
int a[MAXN],b[MAXN],c[MAXN];
int main()
{
    // freopen("input.txt","w",stdout);
    //  data_gene(10000);
    //freopen("input.txt","r",stdin);
    int ca;
scanf("%d",&ca); while(ca--) { int n,m; scanf("%d %d",&n,&m); scanf("%s",s); int clen = strlen(s); for(int i = 0; i<clen; ++i) c[i] = s[i]-'0'; bool ok = 0; for(int a1 = 1; a1 <= 9; ++a1) { int
f = 1,p = 0; for(int i = 1; i<=m; ++i) { int t1 = c[p]; if(t1 == 0) { p++; b[i] = 0; } else if(t1 < a1) { t1 = t1 * 10 + c[p+1]; if(t1 % a1 != 0) { f = 0; break; } b[i] = t1/a1; p+=2; } else { if(t1 % a1 != 0) { f = 0; break; } b[i] = t1/a1; p++; } } if(!f) continue; a[1] = a1; for(int i = 2; i<=n; ++i) { int t1 = c[p]; int ta; if(t1 == 0) { ta = 0; p++; } else if(t1 < b[1]) { t1 = t1*10 + c[p+1]; if(t1 % b[1] != 0) { f = 0;break; } p+=2; ta = t1/b[1]; } else { p++; if(t1 % b[1] != 0) { f = 0;break; } ta = t1/b[1]; } bool ff = 1; for(int j = 2; j<=m; ++j) { int t2 = ta*b[j]; if(t2 == c[p]) { p++; } else if(t2 == c[p]*10 + c[p+1]) p+=2; else { ff = 0; break; } } if(ff) a[i] = ta; else { f = 0; break; } } if(!f) continue; if(p != clen) continue; ok = 1; for(int i =1; i<=n; i++) printf("%d",a[i]); printf(" "); for(int i = 1; i<=m; i++) printf("%d",b[i]); printf("\n"); break; } if(!ok) puts("Impossible"); } return 0; }