1257: [CQOI2007]余数之和sum

1257: [CQOI2007]余数之和sum

Time Limit: 5 Sec  Memory Limit: 162 MB
Submit: 2001  Solved: 928
[Submit][Status]

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

Source

数论

题解:第一反应很明显——直接枚举,但是肯定TLE,于是我们发现X mod Y=X-[X/Y],这样子X的累计不难,于是乎关键问题转化为了[X/Y]的累计,当Y>=X时不用说啥,关键是Y<X时,假如O(N)的话,那么还是白搞了。。。所以可以考虑缩减到trunc(sqrt(n))级别——对于这一范围内的数直接算,对于商为[N/I]的只需要用二分确定其范围,然后直接累加,别的没了(Ps:1.注意开int64 2.注意考虑N<K的情况,设一个门楣 3.注意在商运算过程中考虑拍掉重复值,我为此WA了一次)

1 var


 3    i,j,k,l,m,n:longint;
 4 function min(x,y:longint):LONGINT;
 5          BEGIN
 6               IF X<Y THEN MIN:=X ELSE MIN:=Y;
 7          end;
 8 function max(x,y:longint):longint;
 9          begin
10               if x>y then max:=x else max:=y;
11          end;
12 
13 function find1(x,y:longint):longint;
14          var l,r,i,j:longint;
15          begin
16               l:=1;r:=x;
17               while l<r do
18                     begin
19                          if (x div ((l+r) div 2))>y then l:=(l+r) div 2+1 else r:=(l+r) div 2;
20 
21                          i:=1;
22                     end;
23               find1:=r;
24          end;
25 function find2(x,y:longint):longint;
26          var l,r,i,j:longint;
27          begin
28               l:=1;r:=x;
29               while l<(r-1) do
30                     begin
31                          if (x div ((l+r) div 2))>=y then l:=(l+r) div 2 else r:=(l+r) div 2-1;
32 
33                          i:=1;
34                     end;
35               if (x div r)=y then exit(r) else exit(l);
36          end;
37 
38 function ca(x,z:longint):int64;
39          var i,j,a1,a2:longint;
40          y:int64;
41          begin
42               y:=0;
43               for i:=1 to trunc(sqrt(x)) do
44                   begin
45                        if i>z then break;
46                        a1:=min(find2(x,i),z);
47                        a2:=max(find1(x,i),trunc(sqrt(x))+1);
48                        y:=y+(x div i)*i;
49                        if a2<=a1 then y:=y+int64((int64(a1+a2)*int64(a1-a2+1) div 2)*i);
50                   end;
51               exit(y);
52          end;
53 begin
54            begin
55                 readln(m,n);
56                 writeln(int64(n)*int64(m)-ca(n,min(n,m)));
57            end;
58 end.
59

时间: 2024-10-10 22:19:26

1257: [CQOI2007]余数之和sum的相关文章

BZOJ 1257: [CQOI2007]余数之和sum【神奇的做法,思维题】

1257: [CQOI2007]余数之和sum Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 4474  Solved: 2083[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

bzoj 1257: [CQOI2007]余数之和sum 数学 &amp;&amp; 枚举

1257: [CQOI2007]余数之和sum Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 1779  Solved: 823[Submit][Status] 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

BZOJ 1257: [CQOI2007]余数之和sum( 数论 )

n >= k 部分对答案的贡献为 k * (n - k) n < k 部分贡献为 ∑ (k - ⌊k / i⌋ * i)  = ∑  , ⌊k / i⌋ 相等的数是连续的一段, 此时这段连续的数对答案的贡献成等差数列, 可以O(1)求出..然后就分⌊k / i⌋ 相等的一块一块来就行了. 分出来大概是sqrt(k)块.这个sqrt(k)我并不会证Orz...写了个程序验证了一下, 分出来的块数和2 * sqrt(k)非常接近. 所以时间复杂度为O(sqrt(k)) --------------

BZOJ 1257 [CQOI2007]余数之和sum(计数优化)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1257 [题目大意] 给出正整数n和k,计算j(n,k)=k mod 1 + k mod 2 + k mod 3 + … + k mod n的值 [题解] 我们发现k%i=k-[k/i]*i,j(n,k)=n*k-∑[k/i]*i,我们知道[k/i]的取值不超过k^(1/2)个, 并且在分布上是连续的,所以我们可以分段求和,对于段开头l,其段结尾r=k/[k/l]. [代码] #inc

[BZOJ 1257] [CQOI2007] 余数之和sum 【数学】

题目链接:BZOJ - 1257 题目分析 首先, a % b = a - (a/b) * b,那么答案就是 sigma(k % i) = n * k - sigma(k / i) * i     (1 <= i <= n) 前面的 n * k 很容易算,那么后面的 sigma(k / i) * i,怎么办呢? 我们可以分情况讨论,就有一个 O(sqrtk) 的做法. 1)当 i < sqrtk 时,直接枚举算这一部分. 2)当 i >= sqrtk 时, k / i <=

bzoj 1257: [CQOI2007]余数之和sum

这是个神题233(一开始想的也差不多,然而不知道为什么觉得复杂度不对,(没想到等差数列,就GG掉了)) 一个数k,k/x=y...?,?构成等差数列,直接o(1)解决,每得出一个y的区间,是[i,last](last见程序,至于为什么,写写看看,挺显然的) 1 #include<bits/stdc++.h> 2 #define N 100005 3 #define LL long long 4 #define inf 0x3f3f3f3f 5 #define ls tr[x][0] 6 #de

BZOJ 1257 [CQOI2007]余数之和sum ——Dirichlet积

[题目分析] 卷积很好玩啊. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #include <string> #include <iostream> #include <algorithm&

bzoj千题计划173:bzoj1257: [CQOI2007]余数之和sum

http://www.lydsy.com/JudgeOnline/problem.php?id=1257 k%i=k-int(k/i)*i 除法分块,对于相同的k/i用等差序列求和来做 #include<cstdio> #include<iostream> using namespace std; int main() { int n,k; scanf("%d%d",&n,&k); long long ans=0; if(n>k) { an

1257: [CQOI2007]余数之和

1257: [CQOI2007]余数之和 https://www.lydsy.com/JudgeOnline/problem.php?id=1257 分析: $\sum\limits_{n=1}^N k \ mod\ n$ 当n > k时,k mod n都是k,所以直接求就好了. 另一种情况: $\sum\limits_{n=1}^N k - \frac{k}{n} \times n$ 然后对于$\frac{k}{n}$这里进行分块. 代码: 1 #include<bits/stdc++.h&