【问题标题】:Fast way to find a unhappy number快速查找不满意号码的方法
【发布时间】:2015-10-24 22:53:21
【问题描述】:

我正在尝试解决一个问题。给定一个整数范围,用户必须找到给定范围内存在的不快乐的数量。

Unhappy number- 一个数字 n 使得从 n 开始迭代这个数字平方和映射永远不会达到数字 1。

我尝试通过计算数字平方和来使用蛮力方法,如果在任何时刻它等于其中任何一个 (4, 16, 37, 58, 89, 145, 42, 20)那么这是一个不愉快的数字。

这种方法是给TLE有没有更好的方法??

范围在 1 到 10^18 之间。

【问题讨论】:

  • SO 用户,请不要因为无法回答而对问题投反对票!
  • @CrakC 我自己说得再好不过了。仅仅因为有人从未听说过满意的号码或不满意的号码,他们就会投反对票并离开,这很烦人。
  • 快乐数字的维基百科条目列出了确定数字是快乐还是不快乐的编程方法:en.wikipedia.org/wiki/Happy_number#Unhappy_number
  • 哦,我误读了您的评论。好动作@AlbertRenshaw。

标签: c++ math numbers combinations number-theory


【解决方案1】:

您的范围在 1 到 1018 之间。这意味着您的号码最多有 18 位数字。

考虑一个数字的最大平方是 92 = 81,在做一次平方和之后,最大数字是 18 * 81 = 1458。

所以一个平方和加上一个约 1500 个元素的查找表就足够了。

或者两个平方数加上一个约 330 个元素的查找表:

static const bool unhappy[330] {
    1,0,1,1,1,1,1,0,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,0,1,1,1,1,0,1,1,0,0,1,1,1,1,1,
    1,1,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,
    1,1,1,0,1,1,0,1,1,1,0,1,1,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,0,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,
    0,1,0,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,
    1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,1,0,0,1,
    1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,0,1,1,1,1,1,0,1,1,0
}

inline bool is_unhappy(uint64_t n) {
    while (n >= 330) {
        int r = 0;
        while (n > 0) {
            int d = n % 10;
            r += d*d;
            n /= 10;
        }
        n = r;
    }

    return unhappy[n];
}

【讨论】:

    【解决方案2】:
    #include <map>
    #include <set>
    
    bool happy(int number) {
        static std::map<int, bool> cache;
    
        std::set<int> cycle;
        while (number != 1 && !cycle.count(number)) {
            if (cache.count(number)) {
                number = cache[number] ? 1 : 0;
                break;
            }
            cycle.insert(number);
            int newnumber = 0;
            while (number > 0) {
                int digit = number % 10;
                newnumber += digit * digit;
                number /= 10;
            }
            number = newnumber;
        }
        bool happiness = number == 1;
        for (std::set<int>::const_iterator it = cycle.begin();
        it != cycle.end(); it++)
        cache[*it] = happiness;
        return happiness;
    }
    
    #include <iostream>
    
    int main() {
        for (int i = 1; i < 10; i++)
          if (!happy(i))
            std::cout << i << std::endl;
        return 0;
    }
    

    输出:

    2
    3
    4
    5
    6
    8
    9
    

    逻辑和大部分代码取自这里:https://tfetimes.com/c-happy-numbers/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-05
      相关资源
      最近更新 更多