数论分块

这篇博客探讨了一种通过数论分块来优化算法时间复杂度的方法。文章以一个具体的例子展示了如何确定连续数值相同的区间,并给出求区间内数字和的代码实现。在给定的代码中,通过迭代找到最优的分块策略,从而减少计算量。这种方法在处理某些特定问题,如Problem-F-Codeforces题目时,能够提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

例如  n = 20

1   2   3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

20 10 6 5 4 3 2 2 2  2   1   1   1   1   1    1   1   1  1  1

一个明显的规律,使得某个区间(区间长度可能为1)有连续的 \frac{n}{i} 数值相同,

把左右的区间块确定,那问题可以得到优化。

结论

已知 区间的左端点是L ,那么它的右端点是  \frac{n}{n/L}

举例 : 建设 L = 7 时  , n/L = 20/7 = 2 , n/(n/L) = 20/2 = 10   符合区间 [ 7 , 10 ]; 

\sum_{i=1}^{n}[\frac{n}{i}]      求区间内的和

int sum = 0;
for(int l=1,r; l<=n ; l=r+1){
    r = n/(n/l);
    sum += (r-l+1) * (n/l);
}

时间复杂 (O\sqrt{n}

例题

题目:Problem - F - Codeforces

题目的意思就是 左边数字只能减,右边的数字只能加。

我们用数论分块能优化时间;

#include <bits/stdc++.h>
using namespace std;
int f(int n,int m,int x){
    //((m-1)/x + 1 ) * x - m  这里求出x的倍数和m的最小差值  n-x  是求出 n变成x的次数    
    int ans = (((m-1)/x+1)*x-m) + (n-x);
    return ans;
}
int main()
{
    int t,n,m;
    cin >> t;
    while(t--){
        cin >> n >> m;
        if(n>=m){
            cout << n-m << endl;
            continue;
        }
        int ans = 1e9;
        for(int l=1;l<=n;){
            int x = (m-1)/l;
            int r = (m-1)/x;
            r = min(n,r);
            ans = min(ans,f(n,m,l));
            ans = min(ans,f(n,m,r));
            l = r+1;
        }
        cout << ans << endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值