[CQOI2007]余数之和

Sol:https://lunatic.blog.csdn.net/article/details/104024380?spm=1001.2101.3001.6650.12&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-12.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~Rate-12.pc_relevant_default&utm_relevant_index=14

 

https://blog.csdn.net/weixin_45775438/article/details/113485118?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1.pc_relevant_default&utm_relevant_index=1

 

 

 

 

 

 

 

给出正整数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

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <cstdio>
long long n, m, ans;
long long min(long long x, long long y) {
    return x < y ? x : y;
}
int main() {
    scanf("%lld %lld", &n, &m), ans = n * m;
    for (int i = 1, j; i <= n; i = j + 1)
    {
        if (m/i)
            j=min(m / (m / i), n);
        else
            j=n;
         
        ans -= (m / i) * (i + j) * (j - i + 1) / 2;
    }
    printf("%lld\n", ans);
    return 0;
}

  

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
k%i=k-trunc(k/i)*i,当n>k时,直接把长度为(n-k)的区间长度乘以k加入答案,<br>然后就处理i≤k的时候就可以了,然后就用j=n/(n/i)直接跳到(k/i都相等)区间末尾,<br>然后需要对这个区间的等差数列求和加入答案,输出即可。。
注意点:输出%lld,加入答案的时候强制类型转换为long long。。 <br>
精髓点:<br>1:j=n/(n/i)
2:已知区间始末和trunc(k/i)时,求k%i的等差数列的和的公式:
∑=(j-i+1)k-(j-i+1)(i+j)/2*(k/i);
 
#include<cstdio>
#include<iostream>
using namespace std;
int n,k,i,j;
long long ans=0;
int main()
{
    scanf("%d %d",&n,&k);
    if (n>k)
      {
        ans+=(long long)(n-k)*k;
        n=k;
      }
    j=0;
    for (i=1;i<=n;i=j+1)
      {
        j=k/(k/i);
        if (j>=n)
          j=n;
        cout<<"j is   "<<j<<"i is   "<<i;
        system("pause");
        ans+=(long long)(j-i+1)*k-(long long)(j-i+1)*(i+j)/2*(k/i);
//i代表这一段数的开始位置,j是结束位置.则这一段取mod的结果,利用公式k%i=k-trunc(k/i)*i即等于这一段数字的个数*k,再减去这一段用k/i的结果(i是首项,j是尾项,j-i+1是项数,利用等差数列进行求和)
      }
    printf("%lld",ans);
    return 0;
}
 
12 9
j is   1 i is   1请按任意键继续. . .9/1=9..这一段只有一个数
j is   2 i is   2请按任意键继续. . .9/2=4..这一段也只有一个数
j is   3 i is   3请按任意键继续. . .9/3=3..这一段也只有一个数
j is   4 i is   4请按任意键继续. . .9/4=2..这一段也只有一个数
j is   9 i is   5请按任意键继续. . .9/5=1,包括其后的9/6=1,9/7=1,9/8=1,9/9=1.这一段有5个数
39

  

posted @   我微笑不代表我快乐  阅读(157)  评论(0编辑  收藏  举报
努力加载评论中...
点击右上角即可分享
微信分享提示