洛谷P2261 整除分块模板

题意:

给出 n , k n,k n,k,求出
∑ i = 1 n k   m o d   i \sum_{i=1}^{n}k\ mod\ i i=1nk mod i

Solution:

由于 k   m o d   i = k − ⌊ k i ⌋ ⋅ i k\ mod\ i=k-\lfloor\frac{k}{i}\rfloor\cdot i k mod i=kiki,于是只需要求
n k − ∑ i = 1 n ⌊ k i ⌋ ⋅ i nk-\sum_{i=1}^{n}\lfloor\frac{k}{i}\rfloor\cdot i nki=1niki
对于一段使 ⌊ k i ⌋ \lfloor\frac{k}{i}\rfloor ik相同的 i i i,可以利用等差数列求和这一段

现在考虑对于一个 l l l,如何找到最大的 r r r满足
⌊ k l ⌋ = ⌊ k r ⌋ \lfloor\frac{k}{l}\rfloor=\lfloor\frac{k}{r}\rfloor lk=rk
有这样的等式满足
⌊ k l ⌋ = ⌊ k r ⌋ ≤ k r \lfloor\frac{k}{l}\rfloor=\lfloor\frac{k}{r}\rfloor\leq\frac{k}{r} lk=rkrk
于是
r ≤ k ⌊ k r ⌋ = k ⌊ k l ⌋ ⇒ r m a x = ⌊ k ⌊ k l ⌋ ⌋ r\leq\frac{k}{\lfloor\frac{k}{r}\rfloor}=\frac{k}{\lfloor\frac{k}{l}\rfloor}\Rightarrow r_{max}=\lfloor\frac{k}{\lfloor\frac{k}{l}\rfloor}\rfloor rrkk=lkkrmax=lkk

此时找出了最大的 [ l , r ] [l,r] [l,r]使 ⌊ k l ⌋ = ⌊ k r ⌋ \lfloor\frac{k}{l}\rfloor=\lfloor\frac{k}{r}\rfloor lk=rk,只需要对 r + 1 r+1 r+1作为新的左端点时重新计算即可,并且当 ⌊ k l ⌋ = 0 \lfloor\frac{k}{l}\rfloor=0 lk=0时, r = + ∞ r=+\infty r=+。无论何种情况,切莫忘记题目 ≤ n \leq n n的限制

时间复杂度

i ⋅ j = k i\cdot j=k ij=k

i ≤ n i\leq \sqrt{n} in 时, j ≥ n j\geq \sqrt{n} jn ,此时 i i i最多 n \sqrt{n} n 种取值,对应的 j j j只可能有一个取值,于是此时最多有 n \sqrt{n} n ⌊ k i ⌋ \lfloor\frac{k}{i}\rfloor ik

同理对 i ≥ n i\geq \sqrt{n} in ,此时相当于 i , j i,j i,j轮换,取值种数仍然是 n \sqrt{n} n

于是总取值不超过 2 n 2\sqrt{n} 2n 种,时间复杂度 O ( n ) O(\sqrt{n}) O(n )

// #include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#include<bitset>
#include<map>
using namespace std;

using ll=long long;
const int N=1e5+5,inf=0x3fffffff;
const long long INF=0x3fffffffffffffff,mod=1e9+7;

ll n,k;

int main()
{
    cin>>n>>k;
    ll l=1,ans=1ll*n*k;
    while(l<=n)
    {
        ll val=k/l,r=val?min(n,k/val):n;
        ans-=1ll*(l+r)*(r-l+1)/2*val;
        l=r+1;
    }
    cout<<ans;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值