( 数论专题 )【 除法分块 】

( 数论 )【 除法分块 】

模板题目  Gym 101615C

题目描述
对于一个数X,函数f(X)表示X所有约数的和。例如:f(6)=1+2+3+6=12。对于一个X,Smart可以很快的算出f(X)。现在的问题是,给定两个正整数L,R(L<R),Smart希望尽快地算出f(L)+f(L+1)+……+f(R)的值,你能帮助Smart算出这个值吗?

输入格式:
输入文件仅一行,两个正整数L和R(L<R),表示需要计算f(L)+f(L+1)+……+f(R)。

输出格式:
输出只有一行,为f(L)+f(L+1)+……+f(R)的值。

 

先提一个问题,因子7在区间[ 24, 86 ] 里出现了几次?容易的到答案为 86/7 - 23/7 次。

举个例子,当L=1, R=12 , 做出这个因子出现位置图

因子                          1       2       3       4       5       6       7       8       9       10       11       12

因子1出现位置        1       1       1       1       1       1       1       1       1        1          1         1 

因子2出现位置                  2                2                2                2                  2                     2

因子3出现位置                          3                          3                          3                                3   

因子4出现位置                                     4                                  4                                         4

因子5出现位置                                              5                                              5                       

因子6出现位置                                                        6                                                           6

因子7出现位置                                                                 7                                                

因子8出现位置                                                                           8

............

我们要求所有因子和就是把上面的的因子出现位置个数都加起来。

我们根据上图,再做出因子出现次数图。                                                

因子                          1         2         3         4         5         6         7         8         9         10         11         12

出现次数( n/i )    12       6         4         3         2          2       1          1          1          1           1           1

现在我们的答案ans = 1*12 + 2*6 + 3*4 + 4*3 + 5*2 + 6*2 + 7*1 + 8*1 + 9*1 + 10*1 + 11*1 + 12*1 。

显然我们就是要求  \sum_{i=1}^{n} i*[\frac{n}{i}], 好好理解上面的出现次数表!!对应代码哪一部分!!

我们可以看出连续多个1, 连续多个2 ..... 我们就把出现次数相同的因子分成一整块。

这样对于出现次数为1的这一块我们用等差公式求和来算。sum += (n/left)*(right-left+1)*(left+right)/2;

对于左边界我们容易得知等于上一块的右边界加一。

我们知道了左边界,发现右边界等于 左边界因子/出现次数, right = n/(n/left);

然后,下面这个代码的本质其实就是分块求  \sum_{i=1}^{n} i*[\frac{n}{i}]

代码:

#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ll;

ll solve( ll n ) // 求1~n的所以因子和
{
    ll sum=0;
    ll left,right;
    for ( left=1; left<=n; left=right+1 ) { // i这个因子有多少个
        right = n/(n/left);  // 右边界
        sum += (n/left)*(right-left+1)*(left+right)/2;
    }
    return sum;
}

int main()
{
    ll l,r;
    cin >> l >> r;
    cout << solve(r)-solve(l-1) << endl;

    return 0;
}

 

例题2: 余数求和  洛谷P2261

 

分析转自:https://www.luogu.org/problemnew/solution/P2261

代码:

对应上面的代码,只是把公式中的n改成了k, 再特判t是否为0. 重点理解上一题代码是如何分块的

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

ll k,n;

ll solve( ll n ) 
{
    ll sum=0;
    ll left,right;
    for ( left=1; left<=n; left=right+1 ) { 
        ll t = k/left;    // t可能是0, 导致程序出错, 所以需要特判
        if ( t==0 ) right = n;
        else right = min(k/t,n);
        sum += (t)*(right-left+1)*(left+right)/2;
    }
    return sum;
}

int main()
{
    cin >> n >> k;
    cout << n*k-solve(n) << endl;
    return 0;
}

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 除法竖式是一种列式计算法,用于计算两个数的商和余数。其发明的确切时间和人物已经无从考证,但据历史记录,除法竖式的使用可以追溯到古希腊时期。最早的著作之一是欧几里得的《几何原本》,其中包括了一些计算商和余数的方法,类似于现代的除法竖式。 在中国,除法竖式的使用也可以追溯到古代。在中国古代,人们通常使用“竖除法”进行除法计算。竖除法中,被除数、除数和商都写在同一列中,然后从上往下逐位计算。这种方法类似于现代的除法竖式,但使用的是汉字和古代计数法。 除法竖式的基本原理是将被除数和除数写在竖直的列中,然后逐位进行计算。具体步骤包括将除数乘以一个数字,使其接近被除数的某个位数,然后将这个数字写在被除数下面的对应位数上,并进行减法。如果差大于等于除数,就重复这个过程,直到得出商和余数。 除法竖式的使用广泛应用于数学教育和实际计算中。它的发明可以归功于古代的数学家们,他们通过不断尝试和创新,最终发明了这种高效的计算方法。 ### 回答2: 除法竖式是一种用来进行除法计算的方法,它是由古代数学家发明的。大约在公元前4世纪左右,古希腊的数学家欧几里得提出了欧几里得算法,其中包括了一种简单的竖式除法方法。 在古代,人们在进行除法计算时,通常是通过减法来进行逐步计算的。欧几里得观察到这个过程中的共性和规律,他想出了一种改进的方法——竖式除法。 竖式除法是一种逐位计算的方法,通过观察被除数和除数的位数和大小关系,将各位数从左到右逐一除去并记录商和余数。这种方法简化了计算过程,使得除法运算更加清晰和系统。 使用竖式除法的基本步骤如下: 1. 将被除数写在左边,除数写在右边,中间用一条竖线分隔。 2. 从被除数的最左边一位开始,将被除数的这一位与除数的最左边一位进行除法运算,得到商。 3. 将这个商写在除数下面,然后用被除数的这一位减去商乘以除数的果,得到余数。 4. 再将余数的下一位与除数的最左边一位进行运算,得到新的商和余数。 5. 重复第3和第4步,直到所有位数都计算完成。 这种竖式除法的方法极大地方便了除法计算过程,使得计算更加直观和易于理解。到了现代,我们仍然使用这种方法进行除法计算,尤其是在学习数学的过程中,竖式除法也是一种基础的教学工具。通过这些步骤,我们可以清楚地展现除法运算的每一个环节,提高了数学计算的效率和准确性。除法竖式的发明,为我们提供了一种方便而有效的计算方法。 ### 回答3: 除法竖式最早的发明可以追溯到古希腊的数学家尤克里德斯(Euclid)。尤克里德斯是古希腊三大数学家之一,他以发展几何学著称,但他的贡献也包括算术和数论领域。 尤克里德斯采用建立比例、加减乘除等方法,通过形式化的步骤和解决问题的方法,使算术运算变得更加清晰和规范。在其著名的《几何原本》中,他详细描述了算术运算的方法和步骤,其中包括了除法竖式。 除法竖式的发明主要出于简化计算过程和提高计算效率的需要。竖式的排列方式使得数字的对齐更加明确,便于计算者阅读和理解。将除数放在上方的横线上,并在下方逐位写下被除数,之后通过计算商和余数的方法,逐步求解出正确的果。 相对于传统的横式除法,竖式除法明确了每位数的计算过程,避免了一些常见的错误。同时,由于竖式的布局对齐明确,人们能够更方便地在试算过程中进行纠正和修改,提高了计算的准确性和可行性。 尤克里德斯的除法竖式方法在后来的数学教学中被广泛采用,并成为一种标准的计算方式。它简化了除法计算过程,使得学生和计算者能够更轻松地解决除法问题。至今,除法竖式仍然在数学教育中被广泛教授和应用,并被认为是一种便捷和高效的计算方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值