如何减少此程序中大数据集输入的时间复杂度?

时间:2012-04-11 14:03:10

标签: c++ performance

我已编写此代码来计算数字范围之间的设置位数。我的程序编译得很好,并提供适当的输出。大输入和“超出时间限制”需要花费太多时间。

#define forn(i, n) for(long int i = 0; i < (long int)(n); i++)
#define ford(i, n) for(long int i = (long int)(n) - 1; i >= 0; i--)
#define fore(i, a, n) for(long int i = (int)(a); i < (long int)(n); i++)


long int solve(long int i) {
    i = i - ((i >> 1) & 0x55555555);
    i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
    return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}

int main() {
    freopen("C:/Projects/CodeChef/SetBits/input.txt", "rt", stdin);
    freopen("C:/Projects/CodeChef/SetBits/output.txt", "wt", stdout);

    int tt;
    long long int num1;
    long long int num2;
    scanf("%d", &tt);
    forn(ii, tt) {
        unsigned long int bits = 0;
        unsigned long long int total_bits = 0;
        scanf("%lld",&num1);
        scanf("%lld",&num2);
        fore(jj, num1, num2+1) {
                bits = solve(jj);
                total_bits += bits;
                }

        printf("%lld\n",total_bits);
    }

    return 0;
}

示例测试用例: -

示例输入: 3

-2 0

-3 4

-1 4

示例输出:

63

99

37

对于第一种情况,-2包含31 1后跟0,-1包含32 1和0包含0 1。因此,总数是63。

对于第二种情况,答案是31 + 31 + 32 + 0 + 1 + 1 + 2 + 1 = 99

具有大值的测试用例: -

10

-1548535525 662630637

-1677484556 -399596060

-2111785037 1953091095

643110128 1917824721

-1807916951 491608908

-1536297104 1976838237

-1891897587 -736733635

-2088577104 353890389

-2081420990 819160807

-1585188028 2053582020

有关如何优化代码的任何建议,以便花费更少的时间。所有有用的建议和答案将通过投票赞赏。 :)

1 个答案:

答案 0 :(得分:1)

我不知道你在做什么,但我知道你可以清理你的代码,并且你可以内联你的功能。

此外,我已经冒昧地改编了“&#39;你编写代码,你正在使用像C这样的C ++,而那些定义只是严峻,将文件映射到stdio更糟糕。我还没有测试或编译代码,但它就在那里。

#include <fstream>

inline long int solve(long int i) {
    i = i - ((i >> 1) & 0x55555555);
    i = (i & 0x33333333) + ((i >> 2) & 0x33333333);
    return (((i + (i >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24;
}

int main() {
    long first, last;
    unsigned count;
    std::ifstream inf("C:/Projects/CodeChef/SetBits/input.txt");
    std::ofstream off("C:/Projects/CodeChef/SetBits/output.txt");
    inf >> count;
    for(unsigned i=0u; i!=count; ++i) {
        inf >> first >> last;
        long total=0;
        ++last;
        for(long t=first; t!=last; ++t) {
            total+=solve(t);
        }
        off << total << '\n';
    }
    return 0;
}

关于如何加快速度的一些想法:

  • 您可以构建计算值的std :: map,如果它们之前已经处理过,那么请使用它们而不是重新计算。
  • 执行相同但存储范围而不是单个值,但这将是棘手的。 您可以看到地图中是否存在值并通过地图递增,直到没有更多预处理值,在这种情况下开始处理它们以进行迭代。
  • 检查在号码之间是否有一个微不足道的序列,下一个可能是你可以计算出第一个值然后只是递增它。
  • 可能存在用于这种序列的O(1)算法
  • 看一下intel TBB并使用像tbb :: parallel这样的东西来分配每个核心的工作,因为你正在处理这么小的内存或者内存,那么你应该得到一个非常好的大块大小的回报。 / LI>