洛谷

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

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

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

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

记 $ c= lfloorfrac{n}{d} floor $ 则每段 (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