1. 程式人生 > 遊戲 >動作冒險遊戲《Moonscars》推出試玩Demo 2022年發售

動作冒險遊戲《Moonscars》推出試玩Demo 2022年發售

數論分塊

首先我們需要知道數論分塊的用途:它可以快速計算含有除法向下取整的和式。形如\(\sum_{i=1}^{n}f(i)g(\lfloor{\frac{n}{i}}\rfloor)\).為什麼可以快速計算呢,因為那個g的部分我們可以採用分塊的思想快速求解。也就是就\(O(\sqrt{n})\)的時間複雜度裡面求解。

下面講解為什麼是這樣的:

因為\(\lfloor{\frac{n}{i}}\rfloor\)的值是一個塊狀分佈,就是所有的值聚集在一個連續的快裡面。例如:n=21時,我們按照\(\lfloor{\frac{21}{i}}\rfloor\)的值不同,可以把i的值域分為8塊:{1},{2},{3},{4},{5},{6,7},{8,9,10}.{11,12,13,\(\cdots,21\)

}.

這裡我們可以根據影象進行理解:

證明1:分塊的快數需要\(\leq2 \lfloor{\sqrt{n}}\rfloor\)

當我們的\(i\leq\lfloor{\sqrt{n}}\rfloor\),\(\lfloor{\frac{n}{i}}\rfloor\)\(\lfloor{\sqrt{n}}\rfloor\)種取值。這裡我們可以這麼記憶,也就是i從\(1\sim \sqrt{n}\)有多少種不同的取值。然後下取整一下就好了。

\(i\ge\sqrt{n}\)時,\(\lfloor{\frac{n}{i}}\rfloor \leq \lfloor{\sqrt{n}},所以\lfloor{\frac{n}{i}}\rfloor最多有根號n種取值。\)

證明2:i所在塊的右端點是\(\lfloor{\frac{n}{\lfloor{\frac{n}{i}}\rfloor}}\rfloor\)

一定要注意這個k是指i所在塊的值,也就是函式的縱座標.


例題講解

[題目連結]([CQOI2007]餘數求和 - 洛谷)

核心思路:首先我們應該對於k mod i 進行化簡。\(k\pmod{i}=k-(k/i)*i\).然後我們會驚奇的發現後面那一部分就是我們剛開始的求和公式。然後我們就可以採用在\(\sqrt{n}\)的時間複雜度求出來\(t=\lfloor{\frac{k}{i}}\rfloor\).

具體的思路是我們可以利用t在這個\([L,R]\)

這個區間裡面的分塊值不變,注意我們的L和R是已經在一個塊裡面的。然後我們在不斷地迭代更新L和R,因為我們的R是可以通過數論分塊的公式求出來的,所以我們可以L=R+1來迭代更新.

\(對於\sum_{i=1}^{r}i\)這個求和就是很容易的了。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 110, M = 11, MOD = 1e8;

int main()
{
	LL n, k;
	cin >> n >> k;
	LL res = n * k;
	LL l = 1,r;
	while (l <= n)
	{
		if (k / l)
			r = min(k / (k / l), n);
		else//因為一旦k/l等於0就說明這個l已經很大了.所以k/(k/l)就是一個無窮的數了,但是我們右端點最大都是不可以超過n的
			r = n;
		res -= (k / l) * (r - l + 1) * (l + r) / 2;
		l = r + 1;//迭代更新
	}
	cout << res << endl;

}