[codeforces]#350F. Restore a Number

F. Restore a Number

        time limit per test2 seconds
    memory limit per test256 megabytes
            inputstandard input
           outputstandard output

Vasya decided to pass a very large integer n to Kate. First, he wrote that number as a string, then he appended to the right integer k — the number of digits in n.

Magically, all the numbers were shuffled in arbitrary order while this note was passed to Kate. The only thing that Vasya remembers, is a non-empty substring of n (a substring of n is a sequence of consecutive digits of the number n).

Vasya knows that there may be more than one way to restore the number n. Your task is to find the smallest possible initial integer n. Note that decimal representation of number n contained no leading zeroes, except the case the integer n was equal to zero itself (in this case a single digit 0 was used).

Input
The first line of the input contains the string received by Kate. The number of digits in this string does not exceed 1 000 000.

The second line contains the substring of n which Vasya remembers. This string can contain leading zeroes.

It is guaranteed that the input data is correct, and the answer always exists.

Output
Print the smalles integer n which Vasya could pass to Kate.

Examples
input
003512
021
output
30021
input
199966633300
63
output
3036366999
题目大意:给定一组数字字符串,其中包含一个大数和大数的长度,且这些数字被随机存储
第二行为大数包含的子数列
求出这个大数能够得到的最小数
首先求出大数的长度
len为数字字符串的长度,digits从0递增判断(len-digits)的位数+(len-digits)是否与len相等
求出大数的长度
接着求最小数
方法一(有些复杂):
把整个数列分成3部分子数列前pre,子数列,子序列后
基本上是贪心加特殊处理。

#include <cstdio>
#include <set>
#include <vector>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
int cnt[13];
string s;
string remaind, tt;
int len, ll;
int main() {
    cin>> s;
    cin>>tt;
    int len = s.length();
    int n = 0;
    ll = 0;
    if (len == 2) {
        cout << tt << endl;
        return 0;
    }
    for (int i = 0; i < 10; i++) {
        cnt[i] = 0;
    }
    for (int i = 0; i < len; i++) {
        cnt[s[i]-'0']++;
    }
    int t = len-1;
    int digits = 1;
    int dt;
    int f = t;
    dt = 0;
    while (f > 0) {
        f/=10;
        dt++;
    }
    while (t+dt != len) {
        digits++;
        t = len-digits;
        int f = t;
        dt = 0;
        while (f > 0) {
            f/=10;
            dt++;
        }
    }
    len = t;
    while (t) {
        cnt[t%10]--;
        t /= 10;
    }
    int firstt = tt[0]-'0', flag = 0, mintt = 1;
    for (int i = 0; i < tt.length(); i++) {
        cnt[tt[i]-'0']--;
        if (i != 0 && !flag) {
            if (tt[i]-'0' < firstt) {
                flag = 1;
                mintt = tt[i]-'0';
            } else if (tt[i]-'0' > firstt)
                flag = 2;
        }
    }
    int countzero = 0;
    if (mintt == 0) {
        int flagg = 0;
        for (int i = 0; i < tt.length(); i++) {
            if (tt[i] == '0') {
                flagg = 1;
                countzero++;
            } else if (flagg == 1) {
                flag = 3;
                break;
            }
        }
        if (flag == 3 && countzero > cnt[0])
            flag = 1;
    }
    for (int i = 1; i < 10; i++) {
        if (cnt[i] > 0) {
            ll = i;
            break;
        }
    }
    string result;
    if (firstt != 0 && ll != 0) {
        if (ll < firstt) {
            result += (char)(ll+'0');
            cnt[ll]--;
            for (int i = 0; i < firstt; i++) {
                while (cnt[i] > 0) {
                    result += (char)(i+'0');
                    cnt[i]--;
                }
                ll = i+1;
            }
        }
        else if (ll == firstt && cnt[0] > 0 && (mintt != 0 || flag != 1)) {
            result += (char)(ll+'0');
            cnt[ll]--;
            while (cnt[0] > 0) {
                result += '0';
                cnt[0]--;
            }
        }
        if (ll == firstt && flag != 1 && flag != 3) {
            while (cnt[ll] > 0) {
                result += (char)(ll+'0');
                cnt[ll]--;
            }
            ll = ll+1;
        }
    } else if (ll != 0){
        result += (char)(ll+'0');
        cnt[ll]--;
        while (cnt[0] > 0) {
            result += '0';
            cnt[0]--;
        }
    }
    result += tt;
    for (int i = 0; i < 10; i++) {
        while (cnt[i] > 0) {
            result += (char)(i+'0');
            cnt[i]--;
        }
    }
    cout << result << endl;
    return 0;
}

方法二:
把整个数列分成3部分子数列前pre,子数列,子序列后
首先
将字符串best弄成子数列+子序列后的字符串
接着

设置子序列前的首字母为除0最小数字
循环i从0~9 :
在子序列前添加为i的全部数字
判断best是否大于该序列+子序列+子序列后
是就修改
结束循环
输出

#include <functional>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <numeric>
#include <iomanip>
#include <cstdio>
#include <cstring>
#include <cassert>
#include <vector>
#include <math.h>
#include <queue>
#include <stack>
#include <ctime>
#include <set>
#include <map>

using namespace std;

typedef long long ll;
typedef long double ld;

template <typename T>
T nextInt() {
    T x = 0, p = 1;
    char ch;
    do { ch = getchar(); } while(ch <= ' ');
    if (ch == '-') {
        p = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = x * 10 + (ch - '0');
        ch = getchar();
    }
    return x * p;
}

const int maxN = (int)1e6 + 10;
const int maxL = 17;
const int INF = (int)1e9;
const int mod = (int)1e9 + 7;
const ll LLINF = (ll)1e18;

vector <int> a(10);
vector <int> b(10);
char s[maxN];
char t[maxN];

string get(const vector<int>&cnt) {
    string ret = "";
    for (int i = 0; i < 10; ++i) {
        ret += string(cnt[i], char('0' + i));
    }
    return ret;
}

int main() {

  //  freopen("input.txt", "r", stdin);
   // freopen("output.txt", "w", stdout);
    gets(s);
    gets(t);

    if (strcmp(s, "01") == 0 || strcmp(s, "10") == 0) {
        puts("0");
        return 0;
    }

    int n = strlen(s);
    int m = strlen(t);

    for (int i = 0; i < n; ++i) {
        a[s[i] - '0']++;
    }
    for (int i =0 ; i < m; ++i) {
        b[t[i] - '0']++;
    }

    string T = (const char *) t;

    for (int len = 1; ; ++len) {
        vector <int> cnt = a;
        int tmp = len;
        int c = 0;
        while(tmp > 0) {
            cnt[tmp % 10]--;
            tmp /= 10;
            c++;
        }
        bool ok = true;
        for (int i = 0; i < 10; ++i) {
            cnt[i] -= b[i];
            if (cnt[i] < 0) ok = false;
        }
        if (ok && (t[0] != '0' || *max_element(cnt.begin() + 1, cnt.end())) > 0 && n - c == len) {

        } else continue;
        bool have = false;
        string best = "";
        {
            string cur = T + get(cnt);
            if (cur[0] != '0') {
                if (!have || best > cur) {
                    best = cur;
                    have = true;
                }
            }
        }
        string cur = "";
        for (int i = 1; i < 10; ++i) {
            if (cnt[i] > 0) {
                cur += char(i + '0');
                cnt[i]--;
                break;
            }
        }
        for (int i = 0; i <= 10; ++i) {
            string now = cur + T + get(cnt);

            if (now[0] != '0') {
                if (!have || best > now) {
                    best = now;
                    have = true;
                }
            }
            if (i != 10) {
                cur += string(cnt[i], char(i + '0'));
                cnt[i] = 0;
            }
        }
        assert(have);
     //   cout << len << '\n';
        puts(best.c_str());
        exit(0);
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值