洛谷P2261

本文介绍了一种通过找规律的方法解决模运算求和问题的算法。该算法将问题分解为多个等差数列求和,并利用直接求和与分段求和相结合的方式降低时间复杂度。文中还提供了具体的实现代码。

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

点击看题

这道题里面,我基本上是用了找规律的方法,由于这种题是想法题,基本上只能靠意会了……

当然,我还是很良心的,出于自己语文不好,我觉得还是贴一下别人的描述吧(出处:洛古P2261题解):

假设我们要求G(p,k)(p>k),即k mod 1+ k mod 2 + k mod 3 + … +k mod p,我们可以把它分成k部分,分别是k mod ( k + 1 ) + k mod ( k + 2 ) + k mod ( k + 3 ) + … + k mod p和k mod ( k / 2 + 1 ) + k mod ( k / 2 + 2 ) + k mod ( k / 2 + 3 ) + … + k mod k和k mod ( k / 3 +1 ) + k mod ( k / 3 +2 ) + k mod ( k / 3 +3 ) + … + k mod ( k / 2 )和k mod ( k / 4 +1 ) +k mod ( k / 4 +2 ) + k mod ( k / 4 +3 ) + … + k mod ( k / 3 )和……和k mod k/k,分别记作第1部分,第2部分,第3部分……第k部分,可以证明,每一部分都是一个等差数列的和(请读者自己证明这一过程),则可用公式n·(a1+an)/2求得每个部分的值,相加即是答案。

但你会发现这种方法的时间复杂度为O(n),与直接求值的时间复杂度(O(n))相同。怎么办呢?我们可以先用直接求值的方法求出G(sqrt(p),k)的值和前sqrt(p)部分的和(sqrt(x)表示x的算术平方根用去尾法保留整数的值),可以证明,两者的和为G(p,k)(这个的证明应该很容易吧)。

那么问题来了,G(q,k)(q<k)的值是多少呢?方法与上面的类似,只是我们不用求其中一些部分,并且只要在修改一下其中一个部分即可

代码如下:

#include<cmath>
#include<iostream>
using namespace std;
long long n,k,ans=0,i,j;
int main()
{
	cin>>n>>k;
	for (i=2;(double)k/i>=floor(sqrt(k))&&n>k/i;i++)
	ans+=(min(k/(i-1),n)-k/i)*(k%min(k/(i-1),n)+k%(k/i+1))/2;
	if (n>k) ans+=k*(n-k);
	for (j=1;j<=floor(k/(i-1))&&j<=n;j++)
	ans+=k%j;
	cout<<ans;
	return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值