余数之和[BZOJ1257]

欢迎大家访问我的老师的OJ———caioj.cn

题面描述

传送门

思路

∵ k   mod ⁡   i = k − ⌊   k / i ⌋ ∗ i \because k ~\operatorname{mod}~{i}=k-\left\lfloor\ k/i \right\rfloor*i k mod i=k k/ii,原问题转化为:
n ∗ k − ∑ i = 1 n ⌊   k / i ⌋ ∗ i \large n*k-\sum_{i=1}^{n}\left\lfloor\ k/i \right\rfloor*i nki=1n k/ii
对于 ∀ x ∈ [ 1 , k ] \forall x\in [1,k] x[1,k],设 g ⁡ ( x ) = ⌊   k / ⌊   k / x ⌋ ⌋ \operatorname{g}(x)=\left\lfloor\ k/ \left\lfloor\ k/x \right\rfloor \right\rfloor g(x)= k/ k/x

显然,函数 f ( x ) = k / x f(x)=k/x f(x)=k/x单调递减,故 g ⁡ ( x ) ≥ ⌊   k / ( k / x ) ⌋ = x \operatorname{g}(x)\ge \left\lfloor\ k/(k/x) \right\rfloor=x g(x) k/(k/x)=x,转化得: ⌊   k / g ⁡ ( x ) ⌋ ≤ ⌊   k / x ⌋ \left\lfloor\ k/\operatorname{g}(x) \right\rfloor\le\left\lfloor\ k/x \right\rfloor  k/g(x) k/x

另外, g ⁡ ( x ) ≤ k / ⌊ k / x ⌋ \operatorname{g}(x) \le k/\left\lfloor k/x \right\rfloor g(x)k/k/x,则 ⌊   k / g ⁡ ( x ) ⌋ ≥ ⌊   k / ( k / ⌊ k / x ⌋ ) ⌋ = ⌊   k / k ∗ ⌊ k / x ⌋ ⌋ = ⌊   k / x ⌋ \left\lfloor\ k/\operatorname{g}(x) \right\rfloor\ge\left\lfloor\ k/(k/\left\lfloor k/x \right\rfloor)\right\rfloor=\left\lfloor\ k/k*\left\lfloor k/x \right\rfloor\right\rfloor=\left\lfloor\ k/x \right\rfloor  k/g(x) k/(k/k/x)= k/kk/x= k/x

∴ ⌊ k / g ⁡ ( x ) ⌋ = ⌊ k / x ⌋ \therefore \left\lfloor\\ k/\operatorname{g}(x) \right\rfloor=\left\lfloor\\ k/x \right\rfloor k/g(x)=k/x

∀ i ∈ [ x , g ⁡ ( x ) = ⌊   k / ⌊   k / x ⌋ ⌋ ] , ⌊ k / i ⌋ \forall i\in\big[x,\operatorname{g}(x)=\left\lfloor\ k/ \left\lfloor\ k/x \right\rfloor \right\rfloor\big],\left\lfloor k/i\right\rfloor i[x,g(x)= k/ k/x],k/i的值都相等.

∀ i ∈ [ 1 , k ] , ⌊ k / i ⌋ \forall i \in [1,k],\left\lfloor k/i\right\rfloor i[1,k]k/i至多有 2 k 2\sqrt{k} 2k 种取法

∵ \because i &lt; k i&lt;\sqrt{k} i<k i i i k \sqrt{k} k 中取法,所以 ⌊ k / i ⌋ \left\lfloor k/i\right\rfloor k/i至多有 k \sqrt{k} k 种。

又当 i &gt; k i&gt;\sqrt{k} i>k , ⌊ k / i ⌋ \left\lfloor k/i\right\rfloor k/i至多有 k \sqrt{k} k 种。

所以最多有 2 k 2\sqrt{k} 2k

最后用一下等差数列求和。

首项为 x x x,末项为 g ⁡ ( x ) \operatorname{g}(x) g(x),公差为1.

再乘上个 ⌊ k / x ⌋ \left\lfloor k/x\right\rfloor k/x就为所求。

AC code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define ll long long
using namespace std;
ll n,k,ans;
int main()
{
	scanf("%lld%lld",&n,&k);ans=n*k;
	ll gx;
	for(int x=1;x<=n;x=gx+1)
	{
		gx=k/x?min(k/(k/x),n):n;
		ans-=(k/x)*(x+gx)*(gx-x+1)/2;
	}
	printf("%lld\n",ans);
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值