zoukankan      html  css  js  c++  java
  • 【bzoj1257】[CQOI2007]余数之和sum 数论

    题目描述

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

    输入

    输入仅一行,包含两个整数n, k。

    输出

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

    样例输入

    5 3

    样例输出

    7


    题解

    分块

    首先当i>k时,k%i=k,所以如果n>k,直接把答案预先加上(n-k)*k,再把n变成k计算即可。

    然后就是求 ∑(k%i)(1≤i≤n) 的问题。

    考虑到 k%i=k-i*(k/i) ,于是所求即为∑(k-i*(k/i))(1≤i≤n) = n*k-∑(i*(k/i))(1≤i≤n) 。

    这里注意到对于某一个k/i=x的x,能够满足条件i必然是连续的一段。

    那么就可以分块来做。

    对于每个i=last+1,总有last'=min(n,k/(k/i)),满足在且仅在[i,last']区间内的值j符合k/j=k/i。

    然后用一下等差数列求和公式快速求出i~last'的和,再乘上k/i加到答案中即可。

    #include <cstdio>
    #define min(a , b) a < b ? a : b;
    int main()
    {
    	long long n , k , i , last , ans = 0;
    	scanf("%lld%lld" , &n , &k);
    	if(n > k) ans = (n - k) * k , n = k;
    	ans += n * k;
    	for(i = 1 ; i <= n ; i = last + 1)
    	{
    		last = min(n , k / (k / i));
    		ans -= (k / i) * (i + last) * (last - i + 1) / 2;
    	}
    	printf("%lld
    " , ans);
    	return 0;
    }

     

  • 相关阅读:
    Go语言之依赖管理
    Go之NSQ
    Redis相关
    Go语言操作mongoDB
    Go语言操作Redis
    mysql-5.7.22-winx64.zip 安装
    LL(1)文法系列(二)预测分析表
    LL(1)文法系列(三)预测分析程序
    LL(1)文法系列(一)first集和follow集
    算符优先系列之(二)算符优先关系表
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/6556418.html
Copyright © 2011-2022 走看看