BZOJ1257: [CQOI2007]余数之和

这是本人第一篇博客,写的不好请尽力吐槽。
Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 6612 Solved: 3190
[Submit][Status][Discuss]
Description
给出正整数n和k,计算j(n, k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值
其中k mod i表示k除以i的余数。
例如j(5, 3)=3 mod 1 + 3 mod 2 + 3 mod 3 + 3 mod 4 + 3 mod 5=0+1+0+3+3=7
Input
输入仅一行,包含两个整数n, k。
1<=n ,k<=10^9
Output
输出仅一行,即j(n, k)。
Sample Input
5 3
Sample Output
7
首先,我不知道为什么5s的时限下,暴力为什么过不了。
然后,看书看不懂,网上的博客不清不楚。于是,我又重新看了一遍书……
因为 k   m o d   i = k − k~ mod~ i =k- k mod i=k ⌊ k i ⌋ ∗ i \left\lfloor\dfrac{k}{i}\right\rfloor*i iki,所以ans=n*k- ∑ i = 1 n \sum_{i=1}^n i=1n ⌊ k i ⌋ ∗ i \left\lfloor\dfrac{k}{i}\right\rfloor *i iki
对于任意 x x x ∈ \in [ 1 , k ] [1,k] [1,k],设g(x)= ⌊ k / ⌊ k x ⌋ ⌋ \left\lfloor k/\left\lfloor\dfrac{k}{x}\right\rfloor\right\rfloor k/xk.
因为函数 f ( x ) = k / x f(x)=k/x f(x)=k/x(不向下取整)当 x ∈ N + x \in N+ xN+ 时,函数单调递减, g ( x ) &gt; = ⌊ k / f ( x ) ⌋ = x g(x)&gt;=\left\lfloor k/f(x)\right\rfloor=x g(x)>=k/f(x)=x,故 ⌊ k /   g ( x ) ⌋ \left\lfloor k/ \ g(x)\right\rfloor k/ g(x)<= ⌊ k / x   ⌋ \left\lfloor k/ x \ \right\rfloor k/x 

同时, ⌊ k /   g ( x ) ⌋ \left\lfloor k/ \ g(x) \right\rfloor k/ g(x)>= ⌊ k / ( k / ⌊ k / x ⌋ ) ⌋ \left\lfloor k / ( k/ \left\lfloor k/x \right\rfloor) \right\rfloor k/(k/k/x)(除数小,商就大)= ⌊ k / k ∗ ⌊ k /   x ⌋ ⌋ \left\lfloor k/k* \left\lfloor k / \ x \right\rfloor\right\rfloor k/kk/ x=
⌊ k / x   ⌋ \left\lfloor k / x\ \right\rfloor k/x .
所以 ⌊ k /   g ( x ) ⌋ \left\lfloor k/ \ g(x) \right\rfloor k/ g(x)= ⌊ k / x   ⌋ \left\lfloor k / x\ \right\rfloor k/x 
g ( x ) g(x) gx换元得到 ⌊ k /   ⌊ k / ⌊ k i ⌋ ⌋ ⌋ \left\lfloor k/ \ \left\lfloor k/\left\lfloor \dfrac{k}{i} \right\rfloor \right\rfloor \right\rfloor k/ k/ik= ⌊ k / x   ⌋ \left\lfloor k / x\ \right\rfloor k/x (好丑啊)
又因为 f ( x ) f(x) f(x)的性质,所以当 i i i ∈ \in [x, ⌊ k / ⌊ k i ⌋ ⌋ \left\lfloor k/\left\lfloor\dfrac{k}{i}\right\rfloor\right\rfloor k/ik ]时, f ( i ) f(i) f(i)随着 i i i的增大而减小(x恒大于0,反比例函数的性质),那么 ⌊   f ( i ) ⌋ \left\lfloor\ f(i) \right\rfloor  f(i)就是非上升函数,因为两端的 i , ⌊   f ( i ) ⌋ i ,\left\lfloor\ f(i) \right\rfloor i f(i)值都相等了,对于中间的 i , ⌊   f ( i ) ⌋ i ,\left\lfloor\ f(i) \right\rfloor i f(i)也一定相等。
我们就可以把1~n分成若干块,每一块的 ⌊   k / i ⌋ \left\lfloor\ k/i \right\rfloor  k/i都相等,于是就可以用等差数列求和的方法就每一块的值。时间复杂度由 O ( n ) 变 为 O ( √ n ) O(n)变为O(\surd{n}) O(n)O(n)
代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
	ll n,k;scanf("%lld%lld",&n,&k);
	ll ans=n*k;
	for(int i=1,m;i<=n;i=m+1)
	{
		k/i?m=min(n,k/(k/i)):m=n;//分块
		ans-=((k/i)*(i+m)*(m-i+1))/2;//等差数列求和
	}
	printf("%lld\n",ans);
	return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值