• 约数和问题 (codevs2606 && 洛谷2424)


    P2424 约数和

    题目背景

    Smart最近沉迷于对约数的研究中。

    题目描述

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

    输入输出格式

    输入格式:

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

    输出格式:

    输出只有一行,为f(X)+f(X+1)+……+f(Y)的值。

    输入输出样例

    输入样例#1:
    2 4
    输出样例#1:
    14
    输入样例#2:
    123 321
    输出样例#2:
    72543

    说明

    对于20%的数据有1≤X<Y≤10^5。

    对于60%的数据有1≤X<Y≤1*10^7。

    对于100%的数据有1≤X<Y≤2*10^9。

    这题卡了好久,题目很简单很好理解,可推公式的确是件棘手的事

    首先想到的方法是用前缀和的思想,ans [l~r]=ans[1~r] – ans[1~l-1]

    求1~n的约数和,用的是这种方法:

    1:1/2=0           ans=1

    2:2/2=1 2/3=0      ans=1*2+2=4

    3:3/2=1 3/3=1 3/4=0 ans=1*3+1*2+3=8

    4:4/2=2 4/3=1 4/4=1 ans=2*2+1*3+1*4+4=15

    原理很明显

    n除以一个数a,的数就是1~n这些数中以a为因数的数的个数,再乘以a,就是一个因数和

    最后加上n是由于n本身是n的因数

    可是糟糕,这种方法会超时,只得了60分

    60分代码

    #include<iostream>
    using namespace std;
    long long l,r,al,ar;
    long long work(long long a){
        long long result=0;
        for(long long i=2;i<=a;i++){
            if(a/i==0)break;
            result+=(a/i)*i;
        }
        result+=a;
        return result;
    }
    int main(){
        cin>>l>>r;
        al=work(l-1);
        ar=work(r);
        cout<<ar-al;
    }

    无计可施的我在这道题上崩溃了,心塞……

    晚饭后,去找元元问这个题,才终于明白过来

    这题思路是没毛病的,但是TLE的问题说明代码需要优化加速

    用等差数列优化

    首先根据之前的发现,以4为例,会发现4/3=1,4/4=1,同样的,在别的数字上也会出现类似的情况,而且数字越大,这种情况的出现越多,我把3,4分别叫做本例中情况的左右边界。而且不难发现这种情况的连续序列中因数都是等差的,差为一,所以可以直接利用等差数列求和

    最后我发现,这个代码怎么写都丑。

    等差数列求和公式

    #include<iostream>
    #include<cstdio>
    using namespace std;
    long long l,r;
    long long work(long long x){
        long long result=0;
        long long d=1,b;//d是左边界,b是右边界 
        while(1){
            b=x/(x/d);
            long long some=x/d;
            result+=((b+d)*(b-d+1)/2)*some;
            d=b+1;
            if(x/d==0)break;
        }
        return result;
    }
    int main(){
        cin>>l>>r;
        long long al=work(l-1);
        long long ar=work(r);
        cout<<ar-al;
    }
  • 相关阅读:
    Android之dialog
    android上下文菜单(ContextMenu)
    Android中Handler的使用2
    Intent 各种跳转 .
    Android之Adapter用法总结
    android之Menu 实例与详解
    android学习之FrameLayout
    Andriod: 在xml布局中使用自定义属性
    你软考了吗?
    菜鸟从零学习数据库(三)——存储过程
  • 原文地址:https://www.cnblogs.com/thmyl/p/6366220.html
Copyright © 2020-2023  润新知