CQOI2007 余数求和 数学 + 整除分块

博客探讨了一道涉及数学分析和整除分块策略的算法题目,主要出现在洛谷和Acwing平台上。通过分析数据范围和样例,博主揭示了利用等差数列求和公式来优化复杂度,将问题简化为O(1)的时间复杂度。文章详细阐述了如何将问题分块,并展示了简洁的代码实现。
摘要由CSDN通过智能技术生成

题目链接

洛谷

Acwing

思路

一道蓝题,总不可能一个模拟就解决吧。看到数据范围,结合样例,便可知这道题一定是数学分析。具体来说,是一道整除分块题。(可以去科普一下,或者看下面的分析)

易得,                                           k\ mod\ i\ =\ k\ -\ \left \lfloor \frac{k}{i}\right \rfloor *\ i

所以,原式可以转化为

k\ *\ n\ -\ \sum_{i\ =\ 1}^{n}\ \left \lfloor \frac{k}{i} \right \rfloor*\ i

接着观察样例:

i12345678910
k\ mod\ i0121055555

可以发现  \forall i\in [x,\ \left \lfloor k\ /\left \lfloor k\ /\ x \right \rfloor \right \rfloor] ,\   \left \lfloor \frac{k}{i} \right \rfloor  的值都相等

(证明:

 这样就把 n 个数分成了若干组,那时间复杂度是什么呢?

可以发现对于任意的 i ,\left \lfloor \frac{k}{i} \right \rfloor 的值至多由 2\sqrt k\ 段组成,

每一段中 \forall i\in [x,\ \left \lfloor k\ /\left \lfloor k\ /\ x \right \rfloor \right \rfloor] ,\   \left \lfloor \frac{k}{i} \right \rfloor  的值都是 \left \lfloor \frac{k}{x} \right \rfloor

这一段的要计算的就是\sum_{i\ =\ x}^{\left \lfloor k\ /\ \left \lfloor k\ /\ x \right \rfloor \right \rfloor}\ \left \lfloor \frac{k}{x} \right \rfloor*\ i

这样就可以用等差数列求和公式计算,公差为\left \lfloor \frac{k}{x} \right \rfloor 

(首项 + 末项)* 项数 / 2 

那么这一段时间复杂度就是 O(1)

整个程序的时间复杂度就是 O(\sqrt k\

完整Code(非常简短)

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;
LL n, k, res;

int main() 
{
    cin >> n >> k;
    res = n * k;  // 先赋值为 n * k
    
    // 再依次减去每一段的值
    for (int front = 1, rear; front <= n; front = rear + 1)
    {
        // front 这一段的第一个
        // rear  这一段的最后一个
    	rear = k / front ? min(k / (k / front), n) : n;
    	res -= (k / front * front + k / front * rear) * (rear - front + 1) / 2;
        // (首项 + 末项) * 项数 / 2
        // 也可以把 (k / front) 提出来
        // res -= (k / front) * (front + rear) * (rear - front + 1) / 2;
	}
	
	cout << res << endl;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值