• luogu2261 [CQOI2007] 余数之和


    题目大意

    [sum_{i=1}^{n}(kmod i) ]

    (n,kleq 10^9)

    题解

    先只考虑(nleq k)的情况。

    [sum_{i=1}^{n}(kmod i)=sum_{i=1}^{n}k-ilfloor frac{k}{i} floor=kn-sum_{i=1}^{n}ilfloor frac{k}{i} floor ]

    看到

    [sum_{i=1}^{n}lfloor frac{k}{i} floor ]

    则想到整除分块。

    整除分块

    结论:

    [lfloor frac{k}{i} floor=lfloorfrac{k}{lfloorfrac{k}{lfloorfrac{k}{i} floor} floor} floor ]

    规律

    (lfloorfrac{k}{lfloorfrac{k}{i} floor} floor)一定时,所有满足上式的(i)都在一段连续的区间内(组成了一块),区间右端点是(lfloorfrac{k}{lfloorfrac{k}{i} floor} floor)
    因此操作时,直接对一块进行统一操作即可。

    数学推导

    令一块的左端点为(l),右端点为(r)(v=frac{k}{r}),我们现在要求一块内的和

    [sum_{i=l}^{r}iv=sum_{i=0}^{r-l}v(l+i)=vsum_{i=0}^{r-l}(l+i) ]

    此时注意:和式中运算的次数为(r-l-0+1=r-l+1),而不是(r-l)。所以接下来

    [原式 eq v(l(r-l)+sum_{i=0}^{r-l}i) ]

    [原式=v(l(r-l+1)+sum_{i=0}^{r-l}i) ]

    在这里错了就完了!
    最终运用等差数列的知识得到

    [原式=frac{v(r+l)(r-l+1)}{2} ]

    把所有的上式加起来再被(nk)一减即可。

    注意

    边界条件:赋值(r)时,它不能直接等于(lfloorfrac{k}{lfloorfrac{k}{i} floor} floor),而应当是它和(n)的较小值。另外还要考虑(lfloorfrac{k}{i} floor=0)的情况。
    对于(n>k)的情况,把额外值加上即可。要明确(n-k)以及(k)的含义呀!

    #include <cstdio>
    #include <cstring>
    #include <cassert>
    #include <algorithm>
    using namespace std;
    
    #define ll long long
    
    int main()
    {
    	ll n, k;
    	scanf("%lld%lld", &n, &k);
    	ll ans = 0, extra = 0;
    	if (n > k)
    	{
    		extra = (n - k) * k;
    		n = k;
    	}
    	for (ll l = 1, r; l <= n; l = r + 1)
    	{
    		int divVal;
    		r = (divVal = k / l) ? min(n, k / (k / l)) : n;
    		ans += divVal * ((r - l + 1) * (l + r) / 2);
    		assert(ans > 0);
    	}
    	printf("%lld
    ", n * k - ans + extra);
    	return 0;
    }
    
  • 相关阅读:
    linux开启oracle服务
    一个tomcat多域名绑定多项目
    linux安装jdk1.7.0
    windows 查看端口进程和杀死进程
    windows2008 扩大远程连接数
    windows下用bak文件备份数据库
    linux常用命令
    mysql 开启远程连接访问
    windows 下tomcat安装
    IBM公司面试题
  • 原文地址:https://www.cnblogs.com/headboy2002/p/8998455.html
Copyright © 2020-2023  润新知