幸运数字计划(4,7,44,47,74,77,444,......)

时间:2017-04-21 13:12:27

标签: c++ algorithm

我正在研究算法问题解决。

对我来说,有一个问题很难。

有人能给我一些暗示这个问题吗?

以下是问题描述。

  

可以通过总结“LUCKY Numbers”来得出一些数字。   (LUCKY Numbers仅包含“4”和“7”。例如,4,4,44,47,74,77,444,447,474,......)

     

当给出N时,写一个打印LUCKY数字的程序,其总和为N.

     

如果有多种方法,请打印较小数量的方法。   (例如,当N为28时,28 = 7 + 7 + 7 + 7或28 = 4 + 4 + 4 + 4 + 4 + 4 + 4)   但较少数量的LUCKY数字是7 + 7 + 7 + 7。

     

如果有多种方法,则按字典顺序输出最前面的方法。   (例如,当N为11时,11 = 4 + 7或7 + 4)   但按字典顺序排列的LUCKY数字是4 + 7。

     

如果N不能表示为LUCKY数字的总和,则输出-1。   (例如,当N为10时,未使用LUCKY数字表示10。)

1 <= N <= 1000000000

我写了C ++代码。但是,当N很大时,我的程序超过了时间限制(2秒)。

  • 较小的N:11111,5555,...我的程序效果很好。

  • 更大的N:...,999999999,1000000000我的节目超过了时间限制。

以下是我的源代码。

#include <cstdio>
#include <map>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
typedef long long lld;

const lld MAXN = 1e9;
vector<lld> V;

map<lld, lld> M;

//      make LUCKY Numbers
void dfs(lld n) {
    if (n > MAXN)
        return;

    V.push_back(n);
    dfs(n * 10 + 4);
    dfs(n * 10 + 7);
}

void reconstruct(lld current) {
    //      base case.
    if (current == 0LL) {
        return;
    }

    lld previous = M.find(current)->second;
    reconstruct(previous);
    printf("%lld ", current - previous);
}

int main(int argc, char* argv[]) {
    lld N;      scanf("%lld", &N);
    dfs(0LL);
    sort(V.begin(), V.end());

    //      start node is "0"
    queue<lld> Q;
    Q.push(0LL);
    M.insert(make_pair(0LL, -1LL));

    while (!Q.empty()) {
        lld current = Q.front();
        Q.pop();
        if(current==N)
            break;
        if(current>N)   
            continue;

        //      Note. V[0]=0.
        //      So, I consider from index 1.
        for (int i = 1; i < V.size(); i++) {
            lld next = current + V[i];
            if (0LL <= next && next <= MAXN) {
                if (M.find(next) == M.end()) {
                    M.insert(make_pair(next, current));
                    Q.push(next);
                }
            }
        }
    }

    if (M.find((lld)N) == M.end()) {
        printf("-1\n");
    }
    else {
        reconstruct((lld)N);
    }

    return 0;
}

你能给我一些提示吗?

2 个答案:

答案 0 :(得分:2)

请注意,所有幸运数字都可以写为A * 4 + B * 7,但对A和B有一些限制,因此无需生成所有幸运数字。首先解析N = A * 4 + B * 7A的{​​{1}}。获得BA后,找到幸运数字。例如,如果BA = 12 = 1 + 11幸运数字的可能组合为:4,44,77,77。

答案 1 :(得分:0)

这是一种非常有效的方式来打印带有m位数的幸运数字。我相信你可以改变它来解决你的问题:

#include <iostream>
#include <bits/stdc++.h>

using namespace std;

string decimal_to_binary  (int n,int m) {
    string res = "";

    while (n > 0) {
        int digit = n % 2;
        res += digit + '0';
        n /= 2;
    }

    while (res.size() < m) {
        res+="0";
    }

    reverse(res.begin(), res.end());
    return res;
}

int main()
{
    int m;

    cin>>m;

    for (int i = 0; i<(1<<m); i++) {
        for (int j = 0; j<m; j++) {
            if ( (i& (1<<j)) > 0) {
                cout<<7;
            } else {
                cout<<4;
            }
        }

        cout<< endl;
    }
    return 0;
}