小白进阶之路-西安邮电大学第五届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;
}

 

 
posted @ 2020-05-30 17:54  Wise_4  阅读(187)  评论(0编辑  收藏  举报