1. 程式人生 > >牛客網練習賽25A—因數個數和(整除分塊)

牛客網練習賽25A—因數個數和(整除分塊)

題目描述

q次詢問,每次給一個x,問1到x的因數個數的和。

輸入描述:

第一行一個正整數q ;
接下來q行,每行一個正整數 x

輸出描述:

共q行,每行一個正整數表示答案

題意:

給你一個n,求1的因子數+2的因子數+3的因子數+......+n的因子數。

題解:

轉化成求倍數和,等價於1-n中,1的倍數個數+2的倍數個數+3的倍數個數+......+n的倍數個數。

即:\sum_{i=1}^{n}{\left \lfloor \frac{n}{i} \right \rfloor} 的值。暴力鐵定超時咯,觀察n為50時的暴力結果:

不難發現相等的值都是連續的,我們就可以只算一次這個值,再求出這個值的個數,就可以實現加速咯。(整除分塊)

觀察5為什麼有兩個?i=9時,50 / 9 = 5 餘 5;餘數裡面還有一個5,那麼50 / 10 也可以商5咯。每一塊都是這個原理。

#include<iostream>
#include<cstdio>
using namespace std;
int main()
{
    int q,n;
    cin>>q;
    while(q--)
    {
        cin>>n;
        long long ans = 0;
        for(int i=1; i<=n;)
        {
            int val = n/i;           //當前塊的值
            int num = (n%i)/val+1;   //該值的數量
            ans+=num*val;
            i += num;                //加速移到下一塊
        }
        cout<<ans<<endl;
    }
    return 0;
}