• 洛谷P2261余数求和


    传送门啦

    再一次见证了分块的神奇用法,在数论里用分块思想。

    我们要求 $ ans = sumlimits ^{n} _{i=1} (k % i) $ ,如果我没看错,这个题的暴力有 $ 60 $ 分,当然,不甘平凡的我们怎么能为 $ 60 $ 分折腰,我们来看正解打法。

    我们要知道 $ a % b = a-b*lfloorfrac{a}{b} floor$ 。.

    我们代入后得到:

    $ ans = sumlimits^{n}{i=1}(k-ilfloorfrac{k}{i} floor) = n*k-sumlimits^{n}{i=1}(i * lfloorfrac{k}{i} floor) $

    然后我们用分块做,我们最后计算 $ n * k $ 减去每一段的和就好了。

    开始枚举左端点,根据 $ k $ 计算出右端点:

    若 $ lfloorfrac{k}{l} floor eq 0 $ , $ r = min(lfloorfrac{k}{lfloorfrac{k}{l} floor} floor , n) $ 。

    若$ lfloorfrac{k}{l} floor=0 $ ,$ r=n $。

    最后计算每一块的和:
    $ sum = lfloorfrac{k}{l} floor * (r-l+1) *(l+r) / 2$。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    inline long long read(){
    	char ch = getchar();
    	long long f = 1 , x = 0;
    	while(ch > '9' || ch < '0'){if(ch == '-')f = -1;ch = getchar();}
    	while(ch >= '0' && ch <= '9'){x = (x << 1) + (x << 3) + ch - '0';ch = getchar();}
    	return x * f;
    }
    
    long long n,k;
    long long ans;
    
    int main(){
    	n = read(); k = read();
    	ans = n * k;
    	for(int l=1,r;l<=n;l=r+1){
    		if(k / l != 0)  r = min(k / (k / l) , n);
    		else r = n;
    		ans -= (k / l) * (r - l + 1) * (l + r) / 2;
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    顺风不浪,逆风不怂。
  • 相关阅读:
    mongodb的aggregate聚合操作详解
    2013, Lost connection to MySQL server during query
    事务失败的重试策略
    mongodb的shell脚本
    mongodb的currentOp
    mongodb插入数据
    Too many threads are already waiting
    connection timed out
    python3-request.session 的使用
    intellij-永久破解最新版本idea 2020.3.1
  • 原文地址:https://www.cnblogs.com/Stephen-F/p/9885948.html
Copyright © 2020-2023  润新知