給定正整數 N (≤ 5,000,000),計算 [1, N] 中「快樂數」個數。
快樂數定義:對數字各位平方和迭代,最終收斂到 1。否則進入循環(如 4→16→37→58→89→145→42→20→4)。
測試用例 T ≤ 20,單次遍歷 500 萬數字直接模擬會超時。
n ≤ 5,000,000,計算一次位平方和 next(n),查表 isHappy[next(n)] 即知結果。bool isHappy[568],標記 1~567 是否為快樂數。next[n](可選,或實時計算)。N,遍歷 1~N,累加 isHappy[next(i)] 為 true 的計數。prefixHappy[i] = 1~i 快樂數個數,查詢 O(1) 回答。#include <bits/stdc++.h>
using namespace std;
const int MAX_SUM = 7 * 81; // 567
bool isHappy[MAX_SUM + 1];
int prefixHappy[5000001];
int nextNum(int n) {
int sum = 0;
while (n) { int d = n % 10; sum += d * d; n /= 10; }
return sum;
}
void init() {
// 1. 判斷 1~567 快樂數
for (int i = 1; i <= MAX_SUM; i++) {
int slow = i, fast = i;
do {
slow = nextNum(slow);
fast = nextNum(nextNum(fast));
} while (slow != fast);
isHappy[i] = (slow == 1);
}
// 2. 預計算前綴和
for (int i = 1; i <= 5000000; i++) {
prefixHappy[i] = prefixHappy[i-1] + (isHappy[nextNum(i)] ? 1 : 0);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
init();
int T; cin >> T;
while (T--) {
int N; cin >> N;
cout << prefixHappy[N] << '\n';
}
return 0;
}
O(MAX_SUM * 迭代次數) + O(5e6) ≈ 幾千萬操作,< 0.1s。O(1) 每個測試用例。5000001 * 4B ≈ 20MB,符合限制。