《算法竞赛进阶指南》0x32 T2 余数之和
作者:互联网
题目描述
给出正整数 n n n和 k k k,计算 ( k m o d 1 ) + ( k m o d 2 ) + ( k m o d 3 ) + … + ( k m o d n ) (kmod1)+(k mod 2)+(k mod 3)+…+(k mod n) (kmod1)+(kmod2)+(kmod3)+…+(kmodn)的值。
输入格式
输入仅一行,包含两个整数 n n n, k k k。
输出格式
输出仅一行,即 ( k m o d 1 ) + ( k m o d 2 ) + ( k m o d 3 ) + … + ( k m o d n ) (kmod1)+(k mod 2)+(k mod 3)+…+(k mod n) (kmod1)+(kmod2)+(kmod3)+…+(kmodn)的值。
数据范围
1 ≤ n , k ≤ 1 0 9 1≤n,k≤10^9 1≤n,k≤109
输入样例
5 3
输出样例
7
题解 O ( k ) O(\sqrt k) O(k )
很简单的一个道理
k
k
k%
i
i
i=
k
−
⌊
k
/
i
⌋
×
i
k-\lfloor k/i\rfloor \times i
k−⌊k/i⌋×i
所以题目要求的式子就可以转化为
n
×
k
−
n\times k-
n×k−
∑
i
=
1
n
⌊
k
/
i
⌋
×
i
\sum_{i = 1}^{n}\lfloor k/i\rfloor \times i
∑i=1n⌊k/i⌋×i
接下来我们拿n= 9 ,k = 4 为例分析下k/i:
4/1 4/2 4/3 4/4 4/5 4/6 4/7 4/8 4/9
4 2 1 1 0 0 0 0 0
所以最后的结果就是
9
∗
4
−
4
∗
1
−
2
∗
2
−
1
∗
(
3
+
4
)
−
0
∗
(
5
+
6
+
7
+
8
+
9
)
9*4-4*1-2*2-1*(3+4)-0*(5+6+7+8+9)
9∗4−4∗1−2∗2−1∗(3+4)−0∗(5+6+7+8+9)
用l和r来表示一个连续区间的左端点和右端点,再通过等差数列通项公式
(
l
+
r
)
∗
(
r
−
l
+
1
)
/
2
(l+r)*(r-l+1)/2
(l+r)∗(r−l+1)/2求出这一段数字的总和再乘上
(
k
/
l
)
(k/l)
(k/l)。
通过以上这种方式就可以避免遍历
1
−
n
1-n
1−n,大大减少循环次数
code
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,k;
cin>>n>>k;
int r;
long long ans;
ans=(long long)n*k;
for(int l=1;l<=n;l=r+1)
{
if(k/l==0) break;//超出范围,退出循环
r=min(k/(k/l),n);//求出右端点,再与n求最小值,防止超出范围
ans-=(long long)(k/l)*(l+r)*(r-l+1)/2;//公式
}
cout<<ans;
return 0;
}
标签:进阶,int,ans,T2,long,times,0x32,kmod1,mod 来源: https://blog.csdn.net/weixin_55355427/article/details/114291723