【除法分块 && 找规律】LightOJ - 1245 Harmonic Number (II)

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被计算了两次。所以得减去一次的值。例如 8 就没有被重复计算。

#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;// n/i 加了一次,(n/i - n/(i + 1)) * i 也加了一次。
        printf("Case %d: %lld\n", Case++, ans);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
    int T, n, Case = 1;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        ll ans = 0;
        ll i;
        for(i = 1; i <= n;)
        {
            ll t = n/i;
            ll num = n/t-n/(t+1);// n/i 的个数
            ans += t*num;
            i += num;// 跳出 n/i = t 的范围
        }
        printf("Case %d: %lld\n", Case++, ans);
    }
    return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
    int T, n, Case = 1;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d", &n);
        ll ans = 0;
        ll i, r;
        for(i = 1; i <= n; i = r+1)
        {
            r = n/(n/i);// n/i 的边界,r-i+1 = n/i 出现次数 = n/(n/i) - n/(n/i+1),i = n/(n/i+1)+1,r = n/(n/i)
            ans += n/i*(r-i+1);//(r-i+1) 为 n/i 出现的次数
        }
        printf("Case %d: %lld\n", Case++, ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值