zoukankan      html  css  js  c++  java
  • [余数求和]整除分块

    Description

    给出整数(n,k),计算(G(n,k)=sumlimits_{i=1}^n=k mod i),(1<=n,k<=1e9)

    Solution

    将k mod i展开可以得到
    (k - i*lfloor frac{k}{i} floor)
    将求和式子展开可以得到
    (sumlimits_{i=1}^n=n*k-sumlimits_{i=1}^n i*lfloorfrac{k}{i} floor)
    利用整除分块,可以发现,对于相同的(lfloorfrac{k}{i} floor),即每个区间(l 到 r),每次只需要再对i求和即可
    即每次计算((r-l+1)*lfloor frac{k}{i} floor * (l+r)/2)

    Note

    在分块的时候误写为r=N/(N/i)导致调试耽误大量时间,而且交了四发才发现

    for (ll l = 1, r; l <= N; l = r + 1) {
            if (l > K) {
                break;
            }
            r = min(N, K/(K/l));
            ans -= (r - l + 1)*(K/l)*(l + r)/2;
        }
    

    Code

    //https://www.luogu.com.cn/problem/P2261
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <queue>
    #include <cmath>
    #include <map>
    #include <set>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define debug cout<<0<<endl
    #define ll long long
    const int MAXN = 1e2 + 10;
    const int MOD = 1e9 + 7;
    using namespace std;
    
    ll ans = 0;
    
    void solve(ll N, ll K) {
        ans = N*K;
        for (ll l = 1, r; l <= N; l = r + 1) {
            if (l > K) {
                break;
            }
            r = min(N, K/(K/l));
            ans -= (r - l + 1)*(K/l)*(l + r)/2;
        }
        cout << ans;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0);
        ll N, K; cin >> N >> K;
        solve(N, K);
        return 0;
    }
    
  • 相关阅读:
    libevent-2.0.so.5 (安装MEMCACHED问题)
    MySQL的show语句大全
    远程客户端连接MysqL数据库太慢解决方案
    用SQL命令查看Mysql数据库大小
    elasticsearch-head安装及启动
    logstash收集IIS日志
    备份并删除7天以前数据
    shell脚本递归压缩实践
    二目运算符 “->”
    关于int main( int argc, char *argv[] )
  • 原文地址:https://www.cnblogs.com/ez4zzw/p/12898048.html
Copyright © 2011-2022 走看看