zoukankan      html  css  js  c++  java
  • BZOJ2956: 模积和——整除分块

    题意

    求 $sum_{i=1}^n sum_{j=1}^m (n mod i)*(m mod j)$($i eq j$),$n,m leq 10^9$答案对 $19940417$ 取模。

    分析:

    由于取模可化成取整的形式,$k mod i = k - left lfloor frac{k}{i} ight floor * i$,详见 BZOJ1257 余数之和

    易知,$sum_{i=1}^n sum_{j=1}^m (n mod i)*(m mod j) = sum_{i=1}^n(n mod i)sum_{j=1}^m(m mod j)$

    所以答案为两部分余数和的乘积减去 $i$ 等于 $j$ 的情况,

    当 $i=j$ 时,
    $$
    egin{aligned}
    sum_{i=1}^{min(n,m)}(n mod i)(m mod i)  & = sum_{i=1}^{min(n,m)}(n - left lfloor frac{n}{i}  ight  floor  i)(m - left lfloor frac{m}{i} ight floor  i) \
    &= sum_{i=1}^{min(n,m)}(nm - mleft lfloor frac{n}{i} ight floor  i - nleft lfloor frac{m}{i} ight floor i + left lfloor frac{n}{i} ight floor left lfloor frac{m}{i} ight floor i^2)  \
    end{aligned}$$

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    const ll mod = 19940417;
    const ll inv6 = 3323403;
    ll n, m;
    
    //sum_1^n [k/i]*i
    ll S1(ll n, ll k)
    {
        ll ret = 0;
        if(k <= n)   //需要分类讨论
        {
            for(ll i = 1,j;i <= k;i = j+1)
            {
                j = k / (k / i);
    
                ret = (ret + (i+j) * (j-i+1) / 2 % mod * (k / i) % mod) % mod;
            }
        }
        else
        {
            for(ll i = 1,j;i <= n;i = j+1)
            {
                j = min(k / (k / i), n);
                ret =  (ret + (i+j) * (j-i+1) / 2 % mod * (k / i) % mod) % mod;
            }
        }
    
        return ret;
    }
    
    ll S2(ll n)
    {
        n %= mod;
        return n * (n+1) % mod * (2*n+1) % mod * inv6 % mod;
    }
    
    //[n/i][m/i]i^2
    ll S3(ll n, ll m)
    {
        ll ret = 0;
        for(ll i = 1,j;i <= min(n, m);i = j+1)
        {
            j = min(n/(n/i), m/(m/i));
            ret = (ret + (n/i) * (m/i) % mod * (S2(j) - S2(i-1)) % mod) % mod;
        }
        return ret;
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        if(m > n) swap(n, m);
        ll ans = 1;
        ans = ans * (n*n%mod - S1(n, n) + mod) % mod;
        ans = ans * (m*m%mod - S1(m, m) + mod) % mod;
        ll ans2 = n *m % mod * m % mod;
        ans2 = (ans2 - m * S1(m, n) % mod) % mod;
        ans2 = (ans2 - n * S1(m, m) % mod) % mod;
        ans2 = (ans2 + S3(n, m)) % mod;
        //printf("%lld %lld
    ", ans, ans2);
        printf("%lld
    ", (ans - ans2 + 2*mod) % mod);
        return 0;
    }

    参考链接:https://www.cnblogs.com/henry-1202/p/10201032.html

  • 相关阅读:
    ssh: connect to host port 22: Connection refused
    mysql安装出现 conflicts with mysql*的解决办法
    Linux 搭建互信后,仍需要密码验证
    正则表达式的小技巧
    基础的正则表达式与re模块(2)
    包的导入
    import模块
    模块的导入
    logging 模块
    hashlib 模块
  • 原文地址:https://www.cnblogs.com/lfri/p/11348561.html
Copyright © 2011-2022 走看看