咱們在線篩的同時處理出每一個數的全部質因子,記憶化搜索的時候直接枚舉質因子便可。
時間複雜度爲 O(nlogn)O(nlogn)O(nlogn)
Code:spa
#include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector> using namespace std; const int maxn = 1000000 + 10; vector<int>G[maxn]; int vis[maxn]; int prime[maxn], n, dp[maxn]; inline void init(){ int cnt = 0; for(int i = 2;i <= n; ++i){ if(!vis[i]) prime[++cnt] = i; for(int j = 1;j <= cnt && i * prime[j] <= n; ++j){ vis[i * prime[j]] = prime[j]; if(i % prime[j] == 0) break; } int k = i; while(vis[k]){ G[i].push_back(vis[k]); int u = vis[k]; while(k % u == 0) k /= u; } if(k != 1)G[i].push_back(k); } } int d(int u){ if(dp[u] != -1) return dp[u]; dp[u] = maxn; for(int i = 1;u - i >= 1 && i <= 6; ++i){ dp[u] = min(dp[u], d(u - i) + i); if(!vis[u - i]) break; } int siz = G[u].size(); for(int i = 0;i < siz; ++i) dp[u] = min(dp[u], d(u / G[u][i]) + 1); return dp[u]; } int main(){ n = maxn - 3; init(); memset(dp, -1, sizeof(dp)); for(int i = 2;i <= n; ++i) if(!vis[i]) dp[i] = 1; dp[1] = 0; int h; while(scanf("%d",&h) != EOF) printf("%d\n",d(h)); return 0; }