小白进阶之路-西安邮电大学第五届ACM-ICPC校赛(同步赛)- H-中位因数
链接:https://ac.nowcoder.com/acm/contest/5678/H
#include <cstdio> #define ll long long using namespace std; const int maxn = 1e6 + 100; const int mod = 1e9 + 7; ll f[maxn],g[maxn]; /* * f[i] : <= sqrt(i) 的 i 的因子 * (ll) x : i 的因子中位数 * g[i] : 求和 x */ /* * 思考:这个是从一个学长那里理解来的答案,我一开始思考问题时觉得要找出所有的因数,所以用了个O(n * sqrt(n)) * 的算法,TLE了,看了答案后觉得第一个f[i] 是 i ,当输出后才明白是f[i] : <= sqrt(i) 的 i 的因子。 * 我想,求中位因子,也就没必要便利所有因子,找到最中间的两个因子就好。 * Justing Thiking Hard and Working Hard,and you will get what you want . */ int main() { for(int i = 1;i < maxn;i++) f[i] = 1; // 每个数字的最小因子 1 ; for(int i = 2;i < maxn;i++){ for(int j = i ;j < maxn;j += i){ // j 是 i 的倍数,如果i * i <= j,代表着 i 是当前 j 的 <= sqrt(j) 的因子 if((ll) i * i <= j) f[j] = i; } } g[0] = 0; for(int i = 1;i < maxn;i++){ ll x = (f[i] + i / f[i]) / 2; // f[i] : <= sqrt(i) 的最大因子,i / f[i] : >= sqrt(i) 的最小因子 g[i] = (g[i-1] + x) % mod; } int t;scanf("%d",&t); while(t--){ int x;scanf("%d",&x); printf("%lld\n",g[x]); } return 0; }