这是本人第一篇博客,写的不好请尽力吐槽。
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
⌊ik⌋∗i,所以ans=n*k-
∑
i
=
1
n
\sum_{i=1}^n
∑i=1n
⌊
k
i
⌋
∗
i
\left\lfloor\dfrac{k}{i}\right\rfloor *i
⌊ik⌋∗i。
对于任意
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+
x∈N+ 时,函数单调递减,
g
(
x
)
>
=
⌊
k
/
f
(
x
)
⌋
=
x
g(x)>=\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/k∗⌊k/ 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)
g(x)换元得到
⌊
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;
}