[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 |
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步