CF-edu#5 E - Sum of Remainders -数学-枚举

本文解析了CodeForces上的一道题目E,通过将原问题转化为求和问题,并利用向下取整特性进行优化,实现了高效求解。文章提供了一种新颖的方法来计算n mod 1 + n mod 2 + ... + n mod m 的值。

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

http://codeforces.com/contest/616/problem/E

给n,m,求Calculate the value of the sum: n mod 1 + n mod 2 + n mod 3 + ... + n mod m

答案对1e9+7取模


一开始不知道怎么做,听了菊苣解说才会了。。。。


把 n%k看成 n-k*(n/k)      n/k是指向下取整

那么sum=  n*m  -    【 1*n/1+ 2*n/2  + ...+ k*n/k +....m*n/m 】;


那么对于后面的部分,当k较小时,直接做,当k较大时,我们可以知道  会有 很多个数 的n/k值是同一个,我们枚举这个n/k值即可

  

// sum: k* [n/k],我们枚举n/k的值,我们称为A值
//从n/end,到n/sqt
//那么对于某个A值,n/A得到对应的起始数x,n/(A+1)得到对应的结束数y
//然后x到y都对应同一个A值,所以直接求x->y的和 乘上A即可


<span style="font-size:12px;">#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iostream>
using namespace std; 
const __int64 mod=1000000007;
__int64 min(__int64 a,__int64 b)
{return a<b?a:b;}

__int64 get (__int64 x)
{
	x%=mod;
	return (x+1)*x/2%mod;
} 

__int64 deal_res(__int64 n,__int64 m)
{
	__int64 end=min(n,m); 
		__int64 ret=0,i;
		int sqt=sqrt(double(n));
		for (i=1;i<=sqt&&i<=end;i++)		
		{
			ret+=n/i*i; ret%=mod;
		} 
		// sum: k* [n/k],我们枚举n/k的值,我们成为A值
		//从n/end,到n/sqt
		//那么对于某个A值,n/A得到对应的起始数x,n/(A+1)得到对应的结束数y
		//然后x到y都对应同一个A值,所以直接求x->y的和 乘上A即可
		sqt++;
		for (i=n/sqt;i>=n/end;i--)		
		{
			__int64 t1=n/i,t2=n/(i+1);
			ret=(ret+  (get(min(end,t1))-get(t2))*i%mod  )%mod;
		}
		return ret%mod;  

}
int main()
{

	__int64 n,m;
	scanf("%I64d%I64d",&n,&m);
	__int64 ans=m%mod*(n%mod)%mod;

	__int64 res=deal_res(n,m);
	ans-=res; 
	while (ans<0)
		ans+=mod;  
	printf("%I64d\n",ans%mod);
	return 0;
	
}</span>


// sum: k* [n/k],我们枚举n/k的值,我们称为A值
//从n/end,到n/sqt
//那么对于某个A值,n/A得到对应的起始数x,n/(A+1)得到对应的结束数y
//然后x到y都对应同一个A值,所以直接求x->y的和 乘上A即可
### PTA 7-3 中国余数定理 的解法 #### 背景介绍 中国余数定理(Chinese Remainder Theorem, CRT)是一种解决同余方程组的方法。给定一组两两互素的模数 \( m_1, m_2, \ldots, m_k \),以及对应的余数 \( r_1, r_2, \ldots, r_k \),CRT可以找到一个最小正整数 \( x \) 满足以下条件: \[ x \equiv r_i \ (\text{mod} \ m_i), \quad i = 1, 2, \ldots, k. \] 对于本题,假设输入为多个形如 \( (m_i, r_i) \) 的数据对,则可以通过计算这些模数的乘积并利用逆元方法得到最终的结果。 --- #### 数学推导过程 设模数组合为 \( M = m_1 \cdot m_2 \cdot \ldots \cdot m_k \),定义辅助变量 \( M_i = M / m_i \) 表示去掉第 \( i \) 项后的乘积。接着,我们需要找出 \( y_i \) 满足如下关系: \[ y_i \cdot M_i \equiv 1 \ (\text{mod} \ m_i). \] 这一步通过扩展欧几里得算法完成。最后,目标值 \( x \) 可表示为: \[ x = \sum_{i=1}^{k} r_i \cdot M_i \cdot y_i \ (\text{mod} \ M), \] 其中 \( x \) 是满足所有同余式的唯一解[^1]。 --- #### Python 实现代码 以下是基于上述理论的一个具体实现方案: ```python def extended_gcd(a, b): """ 扩展欧几里得算法 """ if b == 0: return 1, 0, a else: x, y, gcd_val = extended_gcd(b, a % b) return y, x - (a // b) * y, gcd_val def chinese_remainder_theorem(moduli, remainders): """ 使用中国剩余定理解方程组 """ total_modulus = 1 for modulus in moduli: total_modulus *= modulus result = 0 for mi, ri in zip(moduli, remainders): Mi = total_modulus // mi _, yi, _ = extended_gcd(Mi, mi) ei = (yi % mi + mi) % mi # 确保ei是非负数 result += ri * Mi * ei return result % total_modulus if __name__ == "__main__": n = int(input()) # 输入方程数量 moduli = [] remainders = [] for _ in range(n): mi, ri = map(int, input().split()) moduli.append(mi) remainders.append(ri) solution = chinese_remainder_theorem(moduli, remainders) print(solution) ``` 此程序首先读取若干对 \( (m_i, r_i) \),随后调用 `chinese_remainder_theorem` 函数返回符合条件的最小非负整数 \( x \)[^4]。 --- #### 关键点解析 1. **扩展欧几里得算法**用于求解线性不定方程中的系数 \( y_i \),这是整个算法的核心部分之一。 2. **模运算性质**确保即使中间结果较大也不会影响最终精度。 3. 如果任意两个模数不互质,则需额外处理可能无解的情况,在这里假设定输入均为合法实例[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值