[Bzoj 2956] 模积和 (整除分块)

整除分块

 一般形式:\(\sum_{i = 1}^n \lfloor \frac{n}{i} \rfloor * f(i)\)。

 需要一种高效求得函数 \(f(i)\) 的前缀和的方法,比如等差等比数列求和或对于积性函数的筛法等,然后就可以用整除分块的思想做。

 

题目解法

 化公式变成比较方便的形式:

  \(\ \sum_{i = 1}^n \sum_{j = 1}^m (n \mod i)(m \mod j), i \ne j\)

 \(= \sum_{i = 1}^n \sum_{j = 1}^m (n - i \lfloor \frac{n}{i} \rfloor)(m - j \lfloor \frac{m}{j} \rfloor) - \sum_{i = 1}^{min(n, m)} (n - i \lfloor \frac{n}{i} \rfloor)(m - i \lfloor \frac{m}{i} \rfloor)\)

 

 乘法分配律展开,化简,令 \(t = min(n, m)\) 得:

  \(\ \sum_{i = 1}^n \sum_{j = 1}^m (n - i \lfloor \frac{n}{i} \rfloor)(m - j \lfloor \frac{m}{j} \rfloor) - \sum_{i = 1}^t (n - i \lfloor \frac{n}{i} \rfloor)(m - i \lfloor \frac{m}{i} \rfloor)\)

 \(= \sum_{i = 1}^n \sum_{i = 1}^m nm + m\sum_{i = 1}^n \sum_{i = 1}^m j \lfloor \frac{n}{i} \rfloor + n\sum_{i = 1}^n \sum_{i = 1}^m \lfloor \frac{m}{j} \rfloor +\)

 \(\sum_{i = 1}^n \sum_{i = 1}^m ij \lfloor \frac{n}{i} \rfloor \lfloor \frac{m}{j} \rfloor - \sum_{i = 1}^t nm + m \sum_{i = 1}^t i \lfloor \frac{n}{i} \rfloor - n \sum_{i = 1}^t i \lfloor \frac{m}{i} \rfloor - \sum_{i = 1}^t i^2 \lfloor \frac{n}{i} \rfloor\)

 \(\sum_{i = 1}^n \sum_{i = 1}^m ij \lfloor \frac{n}{i} \rfloor \lfloor \frac{m}{j} \rfloor\) 等于 \(\sum_{i = 1}^n i \lfloor \frac{n}{i} \rfloor * \sum_{i = 1}^m j \lfloor \frac{m}{j} \rfloor\),一个一个算即可。

 

 代码写的比较长……因为用 \(unsigned ll\) 为了避免出负数也多了很多取模……

#include <queue>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

typedef unsigned long long u64;

const u64 mod = 19940417;
const u64 inv_6 = 3323403;

inline u64 Calc_1(u64 l, u64 r) { return (l + r) * (r - l + 1) / 2 % mod; }
inline u64 Calc_2(u64 x) { return ((x + 1) * (2 * x + 1) % mod) * (x * inv_6 % mod) % mod; }

int main(int argc, const char *argv[])
{
  u64 n = 0, m = 0, t = 0, ans = 0, sum_1 = 0, sum_2 = 0;
  scanf("%llu%llu", &n, &m);
  ans = ((n * m % mod) * (n * m % mod) % mod);
  t = min(n, m), ans = (ans + mod - (n * m % mod) * t % mod) % mod;
  for(u64 tmp, l = 1, r = 1; l <= n; l = r + 1) {
    tmp = n / l, r = n / tmp;
    ans = (ans + mod - (Calc_1(l, r) * tmp % mod) * (m * m % mod) % mod) % mod;
    sum_1 = (sum_1 + Calc_1(l, r) * tmp % mod) % mod;
  }
  for(u64 tmp, l = 1, r = 1; l <= m; l = r + 1) {
    tmp = m / l, r = m / tmp;
    ans = (ans + mod - (Calc_1(l, r) * tmp % mod) * (n * n % mod) % mod) % mod;
    sum_2 = (sum_2 + Calc_1(l, r) * tmp % mod) % mod;
  }
  for(u64 tmp, l = 1, r = 1; l <= t; l = r + 1) {
    tmp = n / l, r = min(t, n / tmp);
    ans = (ans + Calc_1(l, r) * (tmp * m % mod)) % mod;
  }
  for(u64 tmp, l = 1, r = 1; l <= t; l = r + 1) {
    tmp = m / l, r = min(t, m / tmp);
    ans = (ans + Calc_1(l, r) * (tmp * n % mod)) % mod;
  }
  for(u64 l = 1, r = 1; l <= t; l = r + 1) {
    r = min(t, min(n / (n / l), m / (m / l)));
    ans = (ans + mod - (mod + Calc_2(r) - Calc_2(l - 1)) * ((n / l) * (m / l) % mod) % mod) % mod;
  }
  printf("%llu\n", (ans + sum_1 * sum_2) % mod);

  return 0;
}

原文地址:https://www.cnblogs.com/nanjoqin/p/10261968.html

时间: 2024-08-04 14:40:10

[Bzoj 2956] 模积和 (整除分块)的相关文章

BZOJ 2956 模积和(分块)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2956 [题目大意] 求∑∑((n%i)*(m%j))其中1<=i<=n,1<=j<=m,i≠j. [题解] $∑_{i=1}^{n}∑_{j=1}^{m}((n\mod i)*(m\mod j))(i≠j)$ $=∑_{i=1}^{n}∑_{j=1}^{m}(n-\lfloor n/i\rfloor*i)*(m-\lfloor m/j\rfloor*j)-∑_{i=1}

BZOJ 2956: 模积和

题目 2956: 模积和 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 554  Solved: 257[Submit][Status] Description 求∑∑((n mod i)*(m mod j))其中1<=i<=n,1<=j<=m,i≠j. Input 第一行两个数n,m. Output 一个整数表示答案mod 19940417的值 Sample Input 3 4 Sample Output 1 样例说明 答案为(3

【bzoj2956】模积和 数论+分块

题目描述 求∑∑((n mod i)*(m mod j))其中1<=i<=n,1<=j<=m,i≠j. 输入 第一行两个数n,m. 输出 一个整数表示答案mod 19940417的值 样例输入 3 4 样例输出 1 题解 数论+分块 由于直接求i≠j的情况比较难搞,所以我们可以先求出i可以等于j的和,然后再减去i等于j时的情况. 也就是求∑∑((n mod i)*(m mod j))-∑((n mod i)*(m mod i)). 然后再根据乘法分配律转化为∑(n mod i)*∑

【BZOJ2956】模积和 分块

[BZOJ2956]模积和 Description 求∑∑((n mod i)*(m mod j))其中1<=i<=n,1<=j<=m,i≠j. Input 第一行两个数n,m. Output 一个整数表示答案mod 19940417的值 Sample Input 3 4 Sample Output 1 样例说明 答案为(3 mod 1)*(4 mod 2)+(3 mod 1) * (4 mod 3)+(3 mod 1) * (4 mod 4) + (3 mod 2) * (4 m

【纪中集训2019.3.29】整除分块

题目 描述 ? 本题的背景是整除分块: ? 定义一个数列$a_{n,i} ? = ?\lfloor \frac{n}{i} \rfloor $ ; ? 求$\sum_{i=l}^{r} mex(a_n) $ ; ? 其中\(mex\)表示序列中最小的没有出现过的自然数: ? 答案对\(998244353\)取模 : 范围 ? \(1 \le T \le 65536 \ , \ 1 \le l ,r \le 10^{36}\) : ? 评测系统支持使用 $ _ _ int218 $ ,但是不能直接

LightOJ 1098(均值不等式,整除分块玄学优化)

We all know that any integer number n is divisible by 1 and n. That is why these two numbers are not the actual divisors of any numbers. The function SOD(n) (sum of divisors) is defined as the summation of all the actual divisors of an integer number

luogu2261余数求和题解--整除分块

题目链接 https://www.luogu.org/problemnew/show/P2261 分析 显然\(k\) \(mod\) \(i=k-\lfloor {k/i}\rfloor\) \(\times\) \(i\),于是我们只需要求\(N * k-\sum_{i=1}^N {\lfloor {k/i}\rfloor\times i}\) 这里就需要数论分块,也称作整除分块的知识 结论: \(\forall{i} \in [x,\lfloor {k/{\lfloor {k/x}\rfl

数论分块之整除分块

前言 最近在学莫比乌斯反演,然而只看懂了莫比乌斯函数,然后反演看着一脸懵逼,最后只看懂了数论分块里面的一个分支内容(也是莫比乌斯反演的前置姿势),整除分块 于是写一篇博文记录一下整除分块 整除分块 整除分块是用于快速处理形似 \[ \sum_{i=1}^{n}{\lfloor \frac{n}{i} \rfloor} \] 的式子的方法 很显然,这个可以\(O(n)\)得到答案.但是,在某些题目中,毒瘤出题人将数据加强到了\(10^{10}\)以上,这个时候我们就无法通过\(O(n)\)的解法来

UVALive - 3521 Joseph&#39;s Problem (整除分块)

给定$n,k$$(1\leqslant n,k\leqslant 10^9)$,计算$\sum\limits _{i=1}^nk\: mod\:i$ 通过观察易发现$k\%i=k-\left \lfloor \frac{k}{i} \right \rfloor*i$,因此我们考虑把$\left \lfloor \frac{k}{i} \right \rfloor$的值相同的$i$分成一组直接求和,复杂度为$O(\sqrt{n})$. 整除分块原理(选自某dalao博客) 1 #include<b