首页 > 技术文章 > bzoj1257 [CQOI2007]余数之和sum

wfj2048 2017-03-28 11:29 原文

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。

Output

输出仅一行,即j(n, k)。

Sample Input

5 3

Sample Output

7

HINT

50%的数据满足:1<=n, k<=1000 100%的数据满足:1<=n ,k<=10^9

 

正解:数学+分块。

$k \bmod i=k-\left \lfloor \frac{k}{i} \right \rfloor*i$,然后直接数论分块即可。

注意$k<n$加特判。

 

 1 //It is made by wfj_2048~
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <complex>
 5 #include <cstring>
 6 #include <cstdlib>
 7 #include <cstdio>
 8 #include <vector>
 9 #include <cmath>
10 #include <queue>
11 #include <stack>
12 #include <map>
13 #include <set>
14 #define inf (1<<30)
15 #define il inline
16 #define RG register
17 #define ll long long
18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
19 
20 using namespace std;
21 
22 ll n,k,lim,pos,ans;
23 
24 il void work(){
25     cin>>n>>k; lim=min(n,k);
26     if (n>k) ans+=k*(n-k);
27     for (RG ll i=1;i<=lim;i=pos+1){
28     pos=k/(k/i); if (pos>lim) pos=lim;
29     ans+=(pos-i+1)*k-(k/i)*((i+pos)*(pos-i+1)>>1);
30     }
31     printf("%lld",ans); return;
32 }
33 
34 int main(){
35     File("sum");
36     work();
37     return 0;
38 }

 

推荐阅读