題意:
小明寫了一個大數字 n
,然後再這個數字後面又加了一個數字 k
, k
是 n
的位數
現在小明把完整的數字傳給了小紅, 但是在傳輸的過程中出現了意外,小紅收到的數字的內容是打亂的, 現在知道的是小明還記得 大數字 n
的一部分,也就是他的字串,讓你還原這個數字 n, 且讓這個數字 n 儘可能的小。
記住,不能又前導零, 一個單個的 零 是允許的。
輸入是小紅收到的數
還有小明記住的數
思路:
有一點很容易想到, 這個 n 很大,也就是 n 的位數很多,但是 n 的位數這個數字的位數也就不超過8位, 所以我們就可以枚舉 n 的位數這個數字的位數
。
- 首先判斷這個位數是不是合法
- 如果合法
- 判斷能不能找到最小的數輸出。
- 如果合法
首先判斷這個位數是不是合法,
我們枚舉的位數 x
和 真正剩下的數lens - x
的位數是不是一樣的,
如果是一樣的,再看看枚舉的位數可不可以由剩下的數組成。
如果位數合法判斷能不能組成最小的數。
現在問題轉化成了
有一些數字, 還有一個有數字組成的字符串t, 怎樣組合纔可以讓組成的數最小。
首先考慮能不能組成數, 也就是剩下的數是不是都是 0,
如果都是 0, 0 的個數有多少個,
如果 0 的個數大於1,那就GG, 如果就 1 個, 直接輸出來。
- 如果 t 的開頭是 0, 單獨輸出來。 那麼 t 就一定不是在總串的開頭
- 如果 t 的開頭不是 0, 我們就弄出來兩個字符串
- t 在總串的開頭
- t 不在總串的開頭,這種情況有可能不存在,注意考慮,因爲 剩餘的數字中有可能只有0或者不剩餘數字。
- 最終兩個串比較一下就好了。
反思:
一開始就沒有想到過用兩個串進行比較的事,
一開始想的就是直接把這個最小的串構造出來。就導致要考慮的細節特別多。 這裏少一個東西,那裏少一個東西。
下次再遇到這樣的題,
給你一些數字, 和一個字符串,構造一個最小的數字出來,
兩步走,
- 判斷t串開頭是不是 0,是 0 直接處理
- 不是 0, 構造兩個串出來,進行比較。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+100;
void dbg() {cout << endl;}
template<typename T, typename... A> void dbg(T a, A... x) {cout << a << ' '; dbg(x...);}
#define logs(x...) {cout << #x << " -> "; dbg(x);}
int n,m,lens,lent,a[10],b[10],c[10];
char s[N],t[N],l[N],r[N];
bool solve(int x){ //判斷當前數字的位數是不是滿足條件。位數最多是 1e6, 所以 k 最大就是7位。一個一個判斷。
for (int i = 0; i < 10; ++i)
c[i] = a[i];
if (lens - x <= 0){
return false;
}
int tmp = lens - x,y,len = 0;
while(tmp){
y = tmp % 10;
len++;
c[y]--;
if (c[y] < 0) return false;
tmp /= 10;
}
if (len != x) return false; //我假定的位數 和 真實的位數是不是一樣的,如果不是那就false。
return true;
}
void put0(){ // t 串開頭是 0 的情況。
bool vis = 1;
for (int i = 1; i < 10; ++i){
if (c[i] && vis){
printf("%d",i);
vis = 0;
for (int j = 1; j <= c[0]; ++j)
printf("0");
printf("%s",t+1);
for (int j = 1; j < c[i]; ++j)
printf("%d",i);
} else
for (int j = 1; j <= c[i]; ++j)
printf("%d",i);
}
if (vis) printf("%s\n",t+1);//如果剩下的數字全在t串中,要單獨考慮
printf("\n");
return;
}
bool put(int emmm){
int x = t[1] - '0',y = 0;
for (int i = 1; i < 10; ++i)
y += c[i];
y += x;
if (y == 0 && emmm > 1) return 0; //判斷是不是全零, 如果是一個零還是滿足條件的,否則不滿足條件。
if (x == 0){
put0(); // 首先判斷 t 串的開頭,不能是零, 不然是零的話不可以放在總串的開頭。
return 1;
}
y = 0;
for (int i = 1; i <= lent; ++i)
l[y++] = t[i];
for (int i = 0; i < 10; ++i)
for (int j = 1; j <= c[i]; ++j)
l[y++] = i + '0';
y = 0;
for (int i = 1; i <= 9; ++i)
if (c[i]){
r[y++] = i + '0';
c[i] --;
break;
}
if (y == 0){ // 判斷 去除了T 串, 剩下的數字不能當頭, 如果不能就直接輸出 t 串當頭。
printf("%s\n",l);
return 1;
}
x = t[1] - '0';
for (int i = 2; i <= lent; ++i){
if (t[i] > t[i-1]) break;
if (t[i] < t[i-1]) {
x--;
break;
}
}
for (int i = 0; i < 10; ++i){
for (int j = 1; j <= c[i]; ++j)
r[y++] = i + '0';
if (i == x){
for (int j = 1; j <= lent; ++j)
r[y++] = t[j];
}
}
if (strcmp(l,r) <= 0){ //兩個串進行比較。
printf("%s\n",l);
} else printf("%s\n",r);
return 1;
}
int main(){
scanf("%s",s+1);
scanf("%s",t+1);
lens = strlen(s+1);
lent = strlen(t+1);
for (int i = 1; i <= lens; ++i)
a[s[i] - '0'] ++;
for (int i = 1; i <= lent; ++i){
a[t[i] -'0'] --;
b[t[i] -'0'] ++;
}
for (int i = 7; i > 0; --i){
if (solve(i)) {
if (put(lens - i)) return 0;
}
}
return 0;
}