首页 > 其他分享 >整除分块

整除分块

时间:2023-10-12 15:57:17浏览次数:43  
标签:分块 sum basic times ans 整除 ll mod

证明

数论分块板子求 $ \large \sum_{i=1}^n [n/i]$ ,其中 $n \leq 10^{10}$

很明显,暴力求的复杂度是 $O(n)$ 的,需要优化

其中,例 $n=10$ 时,$[10/4]=[10/5]$ 是有相等的值的

不妨设第一个 $[n/i]=x$ 的数为 $l$

则最后一个有 $[n/i]=x$ 的数 $\large r= [\frac{n}{[n/l]}]$

理由如下:

不妨设 $n=p \times [n/l] + q$ 其中 $p,q$ 为整数,$0 \leq q <[n/l]$

由 $\large r= [\frac{n}{[n/l]}]$ 得 $ r \times [n/l] \geq n$ , $r\times [n/l]+1>n$

所以 $[n/(r+1)]<[n/l]$ , $r$ 为最后一个 $[n/i]=x$ 的数

接下来说明 $[n/l]$ 最多只有 $2\times \sqrt n -1$

当 $1 \leq l \leq \sqrt n$ 时, 一共只有 $\sqrt n$ 个 $l$ ,所以最多只有 $\sqrt n$ 个 $[n/l]$

当 $\sqrt n < l \leq n$ 时,则用 $n$ 同时除去不等式两边 ,有 $\sqrt n > [n/l] \geq 1$ , 最多有 $\sqrt n -1$ 个不同的 $[n/l]$

所以最多有 $2\times \sqrt n -1$ 个不同的 $[n/l]$

ll solve(ll n){
	ll l = 1,r = 0,ans = 0;
	for(;l <= n;l = r + 1) {
		r = n / (n / l);
		ans += (n / l) * (r - l + 1);
	}
	return ans;
}

例题

约数和 P2424

题目链接

求 x 到 y 每个数所有约数的和

显然 $f(n)=\sum_{i=1}^n i \times [n/i]$ ,其中 $f(n)$ 代表 1 到 n 的约数和

对于每个块,$\sum_{i=l}^r i*[n/l]$ 用等差数列求和即可

$(=(r-l+1)\times(l+r) / 2\times [n/l])$

__int128 solve(__int128 n){
	__int128 l = 1, r = 0, ans = 0;
	for(;l <= n;l = r + 1){
		r = min(n / (n / l), n);
		ans += (n / l) * (l + r) * (r - l + 1) / 2;
	}
	return ans;
}

余数求和


$$G(n,k)= ∑_{i=1}^n k \mod i$$

$$
\begin{aligned}
ans &= ∑_{i=1}^n k \mod i\
&= ∑_{i=1}^n (n-[n/i]\times i) \
&=n \times k - ∑_{i=1}^n [n/i] \times i\
\end{aligned}
$$

ll solve(){
	ll l = 1, r = 0, ans = n * m;
	for(;l <= n;l = r + 1){
		if(m / l == 0) break;
		r = min(m / (m / l), n);
		ans -= (m / l) * (l + r) * (r - l + 1) / 2;
	}
	return ans;
}

Sum of Remainders CF616E

$$\sum_{i=1}^m (n \mod i)$$

差不了多少
$$
\begin{aligned}
\sum_{i=1}^m (n \mod i) &= \sum_{i=1}^m(n-[n/i]*i) \
&=m\times n - \sum_{i=1}^{\min(n,m)} [n/i] \times i \
\end{aligned}
$$

__int128 solve(__int128 n) {
    __int128 l = 1, r = 0, ans = n * m % mod;
    m = min(m, n);
    for (; l <= m; l = r + 1) {
        if (n / l == 0)
            break;
        r = min(n / (n / l), m);
        ans -= (l + r) * (r - l + 1) / 2 % mod * (n / l) % mod;
        ans = (ans + mod) % mod;
    }
    return ans;
}

整除分块优化DP

Up the Strip CF1558B

题面描述

你有一张 $ 1 \times n $ 的纸带,由 $ n $ 个格子组成。初始有一个点在 $ n $ 号格子(即左数第 $ n $ 个)中。

假设现在这个点在 $ x\ (x > 1) $ 号格子,每次你可以对这个点进行如下操作中的一种:

  1. 减法。选择一个 $ [1, x - 1] $ 中的正整数 $ y $,将点移动到 $ x - y $ 号格子中。

  2. 除法。选择一个 $ [2, x] $ 中的正整数 $ z $,将点移动到 $ \lfloor \frac{x}{z} \rfloor $ 号格子中。

当点在 $ 1 $ 号格子中时无法移动,操作结束。

求将点从 $ n $ 号格子移到 $ 1 $ 号格子的方案数,答案对给定的模数取模。


易得转移方程

$$f[x]=\sum_{i=1}^{x-1}f[i] + \sum_{i=2}^{x} f[[n/i]]$$

第一部分用前缀和维护,第二个部分可以用整除分块求解。

ll solve(ll n) {
    ll l = 2, r = 0, ans = 0;
    for (; l <= n; l = r + 1) {
        r = n / (n / l);
        ans += (r - l + 1) * f[n / l] % mod;
        ans %= mod;
    }
    return ans;
}
for (ll i = 2; i <= n; i++) {
    f[i] = (sum[i - 1] + solve(i)) % mod;
    sum[i] = sum[i - 1] + f[i];
}

较难的问题

gcd HDU5780

题目链接

$$∑gcd({x}{a}-1,{x}-1) (1\leq a,b\leq n)$$

不妨设 $b>a$ ,则

$$
\begin{aligned}
gcd(xa-1,xb-1)&=gcd(xa-1,xb-1-x{b-a}(xa-1))\
&=gcd(xa-1,xb-1-xb+x)\
&=gcd(xa-1,x-1) \
&=x^{gcd(a,b)}-1
\end{aligned}
$$

很容易想到枚举 $gcd(a,b)$ 的做法:

确定 $gcd(a,b)$ ,然后枚举 $a$ ,则 $b$ 的情况数就等于 $phi[a/gcd(a,b)]$ ($gcd(\frac{a}{gcd(a,b)},\frac{b}{gcd(a,b)})=1$)

答案就等于

$$ \sum_{i=1}^n (\sum_{j=1}^{j*i\leq n}( phi[j] \times 2-1) -1)\times (x^i-1)$$

ll f(ll a, ll b) {
    if (a == 1)
        return b;
    if (a == 0)
        return 1;
    ll w = f(a / 2, b);
    if (a % 2)
        return w * w % mod * b % mod;
    return w * w % mod;
}
ll solve(ll x, ll n) {
    ll ans = 0, sum = 0;
    for (ll i = 1; i <= n; i++) {
        ll w = f(i, x);
        ans -= w - 1;
        ans = (ans + mod) % mod;
        for (ll j = i; j <= n; j += i) {
            sum += phi[j / i];
            ans += (w - 1) * phi[j / i] * 2 % mod;
            ans %= mod;
        }
    }
    return ans;
}

但是会 $TLE$

我们可以想到 $phi[j/i]$ 是一段连续的 $phi[1]$ 到 $phi[n/i]$

所以可以把 $phi$ 前缀和变成 $phif$ 数组

ll solve(ll x, ll n) {
    ll ans = 0, sum = 0;
    ll w = 1;
    for (ll i = 1; i <= n; i++) {
        w = w * x % mod;
        ans -= w - 1;
        ans = (ans + mod) % mod;
        ll cnt = (w - 1) * phif[n / i] % mod * 2 % mod;
        ans += cnt;
        ans %= mod;
    }
    return ans;
}

结果又 $TLE$ 了

但现在的问题也可以转化为求

$$\sum_{i=1}^n (x^i -1) \times(phif[n/i]*2-1)$$

这个可以拆开,就变成了

$$\sum_{i=1}^n x^i \times(phif[n/i]2-1) -\sum_{i=1}^n (phif[n/i]2-1)$$

前面一部分用数论分块的时候,每一块里的和等于

$$\sum_{i=l}^r x^i \times phif[n/l]$$

用等比数列求和可得等于

$$ x^l \times \frac{x^{r-l+1}-1}{x-1} \times phif[n/l]$$

就可以用整除分块啦

ll f(ll a, ll b) {
    if (a == 1)
        return b % mod;
    if (a == 0)
        return 1;
    ll w = f(a / 2, b);
    if (a % 2)
        return w * w % mod * b % mod;
    return w * w % mod;
}
ll solve(ll x, ll n) {
    ll ans = 0;
    ll w = x;
    ll l = 1, r = 0, inv = f(mod - 2, x - 1);
    for (; l <= n; l = r + 1) {
        r = n / (n / l);
        ans -= (r - l + 1) * (phif[n / l] * 2 - 1) % mod;
        ans = (ans + mod) % mod;
    }
    l = 1;
    for (; l <= n; l = r + 1) {
        r = n / (n / l);
        ll o = f(r - l + 1, x);
        ans += w * (o % mod - 1) % mod * inv % mod * (phif[n / l] * 2 - 1) % mod;
        ans %= mod;
        w = w * o % mod % mod;
    }
    return ans;
}

整除分块+矩阵加速

Sequence HDU6395

原题链接

求 $F_n$ ,其中
$$
\left{\begin{aligned}
F_1 &= A \
F_2 &= B \
F_n &=C\cdot{}F_{n-2}+D\cdot{}F_{n-1}+\left\lfloor\frac{P}{n}\right\rfloor
\end{aligned}\right.
$$
$[\frac{P}{n}]$ 一定时,易得
$$
\begin{pmatrix}
F_{n-2} & F_{n-1} &[\frac{P}{n}] \
0 & 0 & 0 \
0 & 0 & 0
\end{pmatrix}

\times

\begin{pmatrix}
0 & C & 0 \
1 & D & 0 \
0 & 1 & 1
\end{pmatrix}
$$

如果 $ \lfloor \frac{P}{n} \rfloor$ 是个定值就很容易用矩阵加速解决,所以我们可以用整除分块求出每个不同的 $ \lfloor \frac{P}{n} \rfloor$ ,再做矩阵加速即可

inline void init() {
    basic.a[1][1] = 0, basic.a[1][2] = c, basic.a[1][3] = 0;
    basic.a[2][1] = 1, basic.a[2][2] = d, basic.a[2][3] = 0;
    basic.a[3][1] = 0, basic.a[3][2] = 1, basic.a[3][3] = 1;
}
inline void ans_init() {
    ans.a[1][1] = a, ans.a[1][2] = b, ans.a[1][3] = P / 3;
    ans.a[2][1] = 0, ans.a[2][2] = 0, ans.a[2][3] = 0;
    ans.a[3][1] = 0, ans.a[3][2] = 0, ans.a[3][3] = 0;
}
void sum(ll KK, ll n) {
    ans.a[1][3] = KK;
    init();
    while (n) {
        if (n & 1)
            ans = ans * basic;
        basic = basic * basic;
        n >>= 1;
    }
}
ll solve() {
    ll l = 3, r = 0;
    for (; l <= n; l = r + 1) {
        if (P / l != 0)
            r = min(P / (P / l), n);
        else
            r = n;
        sum(P / l, r - l + 1);
    }
    return ans.a[1][2];
}

$$\Huge End$$

标签:分块,sum,basic,times,ans,整除,ll,mod
From: https://www.cnblogs.com/yzq-yzq/p/17759683.html

相关文章

  • 整除分块学习笔记
    模型求\(\large\sum^{n}_{i=1}\lfloor{\frac{n}{i}}\rfloor\)假设\(n\)等于10,我们可以列出下表:\(\i\)12345678910\(\frac{10}{i}\)10532211111如果我们的\(n\)更大时,我们可以发现\(\frac{10}{i}\)中有许多重复的地方。我们可以......
  • 学到了,原来 gzip 是种`连续分块`的压缩算法
    作者:张富春(ahfuzhang),转载时请注明作者和引用链接,谢谢!cnblogs博客zhihuGithub公众号:一本正经的瞎扯我想要表述的是:假设有10mb的数据使用gzip算法来压缩。有这样可能的做法:分配10mb的缓冲区,一次压缩10mb分配1mb的缓冲区,每次压缩1mb,分为十次压缩如果压......
  • 给定3个整数a、b、c,计算表达式(a+b)/c的值,/是整除运算。[无解]
    题目4-2:给定3个整数a、b、c,计算表达式(a+b)/c的值,/是整除运算。  给定3个整数a、b、c,计算表达式(a+b)/c的值,/是整除运算。输入格式:输入仅一行,包括三个整数a、b、c,数与数之间以一个空格分开。(-10,000<a,b,c<10,000,c不等于0)输出格式:输出一行,即表达式的值。map......
  • 【整除分块】【DP】ABC239Ex Dice Product 2 题解
    ABC239H简单题。令\(f_i\)表示乘到\(\gei\)的期望。容易得到\(f_i=\dfrac{\sum\limits_{j=1}^{n}f_{\lceil\frac{i}{j}\rceil}}{n}\)。将\(f_i\)移到同一边,去掉系数,有\(f_i=\dfrac{n\sum\limits_{j=2}^{n}f_{\lceil\frac{i}{j}\rceil}}{n-1}\)。提出\(\frac{n-1}{n......
  • 【ACM算法】整数分块
    思考如何计算以下算式:\[\sum_{i=1}^{n}\lfloor\frac{n}{i}\rfloor\qquad(n\le10^6)\]所有人都会觉得这个非常简单,一个for循环可以直接解决,时间复杂度\(O(n)\),但是如果将\(n\)的范围改大一点点,改成\(n\leq10^{12}\)呢?这时如果我们用朴素算法一定会T;但是我们可以手......
  • 分块+ST的RMQ
    期望\(O(n)-O(1)的RMQ\)#include<bits/stdc++.h>#defineintlonglong#defineF(i0,i1,i2)for(inti0=(i1);i0<=(i2);++i0)usingnamespacestd;inlineintrd(){ intx=0,f=0;charch=getchar(); while(!isdigit(ch)){if(ch=='-')f=1;ch=getchar(......
  • [Резюме] 基础数列分块
    Preface分块可以\(O(n\sqrt{n})\)解决不能用线段树解决的问题,即不能快速合并区间信息的问题,是很多高级算法与数据结构的基础。本篇只是作者基础入门的一些感受,例题为\(\text{LOJ}[6277,6285]\),下一步计划学习莫队算法,这里有学习总结。Content0如何分块?考虑将标准块大小定......
  • 可以被K整除连通块的最大数目
    给你一棵n个节点的无向树,节点编号为0到n-1。给你整数n和一个长度为n-1的二维整数数组edges,其中edges[i]=[ai,bi]表示树中节点ai和bi有一条边同时给你一个下标从0开始长度为n的整数数组values,其中values[i]是第i个节点的值。再给你一个整数......
  • 取模算术运算符-应用1-判断一个数能否被另外一个数整除
    C语言中判断一个整数能否被另外一个整数整除,可以使用取模运算符%。不能直接使用两个整数相除来进行计算,因为直接使用两个整数相除,结果只会保留整数,会舍弃掉小数部分。比如使用C语言计算11/2结果为5,但是11是不能被2整除的,计算结果舍弃掉了小数部分。因此需要使用取余运算符。示......
  • json数据传输压缩以及数据切片分割分块传输多种实现方法,大数据量情况下zlib压缩以及by
    json数据传输压缩以及数据切片分割分块传输多种实现方法,大数据量情况下zlib压缩以及bytes指定长度分割。importsysimportzlibimportjsonimportmathKAFKA_MAX_SIZE=1024*1024CONTENT_MIN_MAX_SIZE=KAFKA_MAX_SIZE*0.9defsplit_data(data):""":param......