【数论 && 找规律】LightOJ

来源:互联网 发布:淘宝怎么查排名 编辑:程序博客网 时间:2024/04/29 23:20

Problem Description

long long H( int n ) {
long long res = 0;
for( int i = 1; i <= n; i++ )
res = res + n / i;
return res;
}
让你实现这个代码 题目n的范围(1<=n<2^31)

思路:

显然暴力肯定会超时,所以肯定是找规律,然而我最讨厌这种类型的题。所以就参考了别人的博客
核心:
n/i=1的个数 n/1 - n/2
n/i=2的个数 n/2 - n/3
以此类推。
我们就可以暴力求1-sqrt(n)的n/i的值。同时求出1的个数,2的个数。当n/sqrt(n) == sqrt(n)的时候,sqrt(n)就被重复计算了,例如17/4 = 4.那么4被计算了两次。所以得减去一次的值。

#include<bits/stdc++.h>using namespace std;int main(){    int T, n, Case = 1;    scanf("%d", &T);    while(T--)    {        scanf("%d", &n);        int m = sqrt(n);        if(m * m > n) m--;        long long ans = 0;        long long i;        for(i = 1; i <= m; i++)        {            ans += n / i;            ans += (n/i - n/(i + 1)) * i;        }        i--;        if(n / i == i) ans -= i;//满足代表sqrt(n)被重复计算了,因为n/sqrt(n)对应值的数目只有一个 所以减i*1        printf("Case %d: %lld\n", Case++, ans);    }    return 0;}