#50814: _cpp 2種解法


kenny980721.tu@gmail.com (有事直接私)

學校 : 國立中興大學附屬高級中學
編號 : 290039
來源 : [220.134.29.87]
最後登入時間 :
2025-09-13 17:26:11

1.最直接 但每次都要重算 太慢  

TLE(1s)

#include<iostream> using namespace std; int main(){ int a; while(cin >> a){ long long t=0; while(a!=1){ if(a%2==0)a/=2; else a=3*a+1; t++; } cout << t << endl; } }

在此基礎上 把程式加上ios::sync_with_stdio(0); cin.tie(0); 再把endl改成" \n" 就可以AC了(0.6s ,364KB)

如果再把 cin cout 改成 scanf printf 可以到(0.5s, 84KB)

 

2. DP(動態規劃)

簡單來說就是把已經算過的數字存下來 下一次就不用重複運算

ex:  6 -> 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1

       8     7      6      5      4      3     2      1     0

這樣下次如果算到6 就把步數直接+=8  算到3就+=7 算到10就+=6 ......

本來以為3n+1數列是收斂的 所以陣列大小我只設了10^6而已

記憶體會爆

#include <iostream> #include <vector> using namespace std; vector<long long> dp(1000001,-1); // 儲存已計算過的結果 long long ans(long long n) { if (n == 1) return 0; if (dp[n]!=-1) return dp[n]; if (n % 2 == 0) return dp[n] = 1 + ans(n / 2); else return dp[n] = 1 + ans(3 * n + 1); } int main() { ios::sync_with_stdio(0); cin.tie(0); int a; while (cin >> a) { cout << ans(a) << "\n"; } }

結果後來發現有時數字會變超級大 (最大到約30億) 如果都用陣列存會爆掉

 

所以陣列大小不變,但改成如果>10^6就用第一種的方式算,反之DP

AC(0.4s, 4.2MB)

#include <bits/stdc++.h> using namespace std; vector<int> dp(1'000'001, -1); long long total(long long a) { if (a == 1) return 0; if (a <= 1'000'000 && dp[a] != -1) return dp[a]; long long ans; if (a % 2 == 0) { ans = 1 + total(a / 2); } else { ans = 1 + total(3 * a + 1); } if (a <= 1'000'000) dp[a] = ans; return ans; } int main() { ios::sync_with_stdio(0); cin.tie(0); int a; while (cin >> a) { cout << total(a) << "\n"; } }

如果改成printf scanf -> AC(0.3s, 4.1MB)