方法一:
約數個數定理:
時間複雜度:O(N^3)c++
#include <bits/stdc++.h> using namespace std; int64_t GetNumFac(int64_t x) { int64_t ans = 1; //cout<< x ; for (int64_t i=2; i <= x; i++) { if (x % i)continue; int times = 0; while (x % i == 0) { x /= i; times ++; } ans *= (times + 1); } //cout<<" ** "<<ans<<endl; return ans; } int main() { int64_t n = 1; while (1) { if (n&1) { if (GetNumFac(n) * GetNumFac((n+1)/2) >= 500) break; } else { if(GetNumFac(n/2) * GetNumFac((n+1)) >= 500) break; } n++; } printf("%lld\n",n*(n + 1 )/2); return 0; }
方法二:
要點1:線性篩的應用——用24 和 2 標記48的約數個數
48 = 2^4 * 3^1 num[48] = (4+1)2=10
24 = 2^3 3^1 num[24] =(3+1)2= 8
模擬:
amt[48] = num[24] / (min_pow[i] + 1) (min_pow[prime[j] * i] + 1);
amt[48] = num[24] / (min_pow[i] + 1) * (min_pow[i] + 2);
注意:prime[j] * i 和 i 的最小因子的冪次數必定相差,這個最小的因子必定是prime[j]
中心思想實現用 24 和 2 表示 48的因子個數
要點2:關於三角數的約數規律spa
時間複雜度:O(N)
代碼實現:code
#include<bits/stdc++.h> using namespace std; const int MAX_N = 1e6; int amt[MAX_N+5] = {0}; ///約數個數 int prime[MAX_N + 5] = {0}; ///中間保存素數 int min_pow[MAX_N + 5] = {0}; /// 保存 最小素因子的冪次數+1 int Get_Trinum(int x) { return x * ( x + 1 ) / 2; } void Init_NumOfPrime() { for (int i=2; i <= MAX_N; i++) { if (!prime[i]) { prime[++prime[0]] = i; amt[i] = 2; min_pow[i] = 1; } for (int j=1; j <= prime[0]; j++) { int tmp = i * prime[j]; if (tmp > MAX_N) break; prime[tmp ] = 1; if (i % prime[j]) { min_pow[ tmp ] = 1; amt[tmp] = amt[i] * amt[prime[j]]; } else { min_pow[tmp ] = min_pow[i] + 1; amt[tmp ] = amt[i] / (min_pow[i] + 1 ) * (min_pow[tmp] + 1); break;///注意 : break緣由 :咱們這個題只須要更新最小素因子的冪次數,在不2 和 24 互素的狀況下,48最小素因子的冪次數已經更新了 } } } return ; } int main() { Init_NumOfPrime(); int n = 1; while (1) { if (n&1) { if (amt[n] * amt[(n+1)/2] >= 500) break; } else { if(amt[n/2] * amt[n+1] >= 500) break; } n++; } printf("%d\n",Get_Trinum(n)); return 0; }
總結blog
題意:定義: a的約數和(不包括自己)等於b,b的約數和(不包括自己)等於a,a,b互爲基佬數,求10000之內的基佬數的和
要點:找出約數和與約數定理的關係簡化運算it
#include<bits/stdc++.h> using namespace std; const int MAX_N = 1e6; const int N = 1e4; int sum[MAX_N+5] = {0}; ///約數個數 int prime[MAX_N + 5] = {0}; ///中間保存素數 int min_pow[MAX_N + 5] = {0}; /// 保存 q^n void Init_SumOfPrime() { for (int i=2; i <= MAX_N; i++) ///注意: { if (!prime[i]) { prime[++prime[0]] = i; sum[i] = 1 + i; min_pow[i] = i * i ; } for (int j=1; j <= prime[0]; j++) { int tmp = i * prime[j]; if (tmp > MAX_N) break; prime[tmp ] = 1; if (i % prime[j]) { min_pow[ tmp ] = prime[j] * prime[j]; sum[tmp] = sum[i] * sum[prime[j]]; } else { min_pow[tmp] = min_pow[i] * prime[j]; sum[tmp] = sum[i] * ( min_pow[tmp] - 1 ) / (min_pow[i] - 1 ); break; } } } return ; } int main() { Init_SumOfPrime(); int ans = 0; for (int i = 2; i <= N; i++) { int num1 = sum[i] - i; int num2 = sum[num1] - num1; if (i == num2 && num1 <= N && num2 <= N && num1 != i) { ans += i; } } printf("%d\n",ans); return 0; }