洛谷 - P2424 - 约数和 - 整除分块

https://www.luogu.org/problemnew/show/P2424

\(\sigma(n)\) 为n的所有约数之和,例如 \(\sigma(6)=1+2+3+6=12\) .
\(ans(n)=\sum\limits_{i=x}^{y}\sigma(i)\) .

首先,记 \(f(n)=\sum\limits_{i=1}^{n}\sigma(i)\) ,则 \(ans(n)=f(y)-f(x-1)\) .
对于 \(f(n)=\sum\limits_{i=1}^{n}\sigma(i)\) ,一个直接的做法是枚举i然后枚举i的因子求和,显然会TLE.

考虑直接枚举因子,易知 \(n\) 以内 \(d\) 的一共有 \(\lfloor\frac{n}{d}\rfloor\) 个,
则有 $f(n)=\sum\limits_{d=1}^{n} d * \lfloor\frac{n}{d}\rfloor $ ,类似的形式在余数求和中见过,直接复制:

记 $ c= \lfloor\frac{n}{d}\rfloor $ 则每段 \(d\) 对应相同的一个 \(c\)

import java.io.*;
import java.util.*;
import java.math.*;

public class Main {
    public static void solve(Scanner cin,PrintStream cout){
        while(cin.hasNext()){
            long x=cin.nextLong(),y=cin.nextLong();
            cout.println(sumfenkuai(y)-sumfenkuai(x-1));
        }
    }
    
    public static long sumfenkuai(long n){
        long ans=0;
        for(long l=1,r; l<=n; l=r+1) {
            if(n/l!=0) {
                r=Math.min(n/(n/l),n);
            } else {
                //n/l==0,意味着l>n,所有的后面的下整都是0,分成同一块
                r=n;
                break;
            }
            
            //d={l,l+1,...r}
            //sum(d)=(l+r)*(r-l+1)/2
            //c=n/l=n/r
            
            //ans=sum_d=1^n:(sum(d)*c)
            ans+=(n/l)*(r-l+1)*(l+r)/2;
        }
        return ans;
    }
    
    public static void main(String[] args) {
        //setFileIO("D://test");
        Scanner cin=new Scanner(System.in);
        PrintStream cout=new PrintStream(System.out);
        
        solve(cin,cout);
        
        cin.close();
        cout.close();
    }
    
    public static void FileIO(String filename){
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(filename+".in");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        System.setIn(fis);
        
        PrintStream ps = null;
        try {
            ps = new PrintStream(new FileOutputStream(filename+".out"));
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.setOut(ps);
    }
}

转载于:https://www.cnblogs.com/Yinku/p/10665922.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值