原理不难但是写起来非常复杂的东西。

我觉得讲得非常好懂的博客。   传送门

我们设

$$f(a, b, c, n) = \sum_{i = 0}^{n}\left \lfloor \frac{ai + b}{c} \right \rfloor$$

$$g(a, b, c, n) = \sum_{i = 0}^{n}i\left \lfloor \frac{ai + b}{c} \right \rfloor$$

$$h(a, b, c, n) = \sum_{i = 0}^{n}\left \lfloor \frac{ai + b}{c} \right \rfloor^2$$

先考虑一个结论

$$\left \lfloor \frac{Ax}{y} \right \rfloor = \left \lfloor \frac{A(x \mod y)}{y} \right \rfloor + A\left \lfloor \frac{x}{y} \right \rfloor$$

那么有

$$\left \lfloor \frac{ai + b}{c} \right \rfloor = \left \lfloor \frac{(a \mod c)i + (b \mod c)}{c} \right \rfloor + i\left \lfloor \frac{a}{c} \right \rfloor + \left \lfloor \frac{b}{c} \right \rfloor$$

这个东西可以把$a \geq c$ 或者$b \geq c$的情况转化成$a,b < c$的情况。

F

先看看这个比较好做的$f$。

注意到当$a \geq c$或者$b \geq c$的时候,我们可以用以上的结论把$a$或者$b$降下来,有

$$f(a, b, c, n) = \left \lfloor \frac{b}{c} \right \rfloor(n + 1) + \left \lfloor \frac{a}{c} \right \rfloor \frac{n(n + 1)}{2} + f(a \mod c, b \mod c, c, n)$$

那么当$a, b < c$的时候,有

$$f(a, b, c, n) = \sum_{i = 0}^{n}\sum_{j = 1}^{m}[\left \lfloor \frac{ai + b}{c} \right \rfloor \geq j]$$

为了方便把$\left \lfloor \frac{an + b}{c} \right \rfloor$记为$m$。

$$f(a, b, c, n) = \sum_{i = 0}^{n}\sum_{j = 0}^{m - 1}[\left \lfloor \frac{ai + b}{c} \right \rfloor \geq j + 1]$$

$$= \sum_{i = 0}^{n}\sum_{j = 0}^{m - 1}[ai \geq cj + c - b]$$

$$= \sum_{i = 0}^{n}\sum_{j = 0}^{m - 1}[ai > cj + c - b - 1]$$

$$= \sum_{i = 0}^{n}\sum_{j = 0}^{m - 1}[i > \left \lfloor \frac{cj + c - b - 1}{a} \right \rfloor]$$

注意到这时候$i$这一项可以直接算了。

$$f(a, b, c, n) = \sum_{j = 0}^{m - 1}(n -  \left \lfloor \frac{cj + c - b - 1}{a} \right \rfloor)$$

$$= nm - f(c, c - b - 1, a, m - 1)$$

比较方便。

G

按照套路先做$a \geq c$或者$b \geq c$的情况。

$$g(a, b, c, n) = \left \lfloor \frac{b}{c} \right \rfloor\frac{n(n + 1)}{2} + \left \lfloor \frac{a}{c} \right \rfloor \frac{n(n + 1)(2n + 1)}{6}  + g(a \mod c, b \mod c, c, n)$$

然后接着按照上述套路弄$a, b < c$的情况。

$$g(a, b, c, n) = \sum_{j = 0}^{m - 1}\frac{(n - \left \lfloor \frac{cj + c - b - 1}{a} \right \rfloor)(n + 1 + \left \lfloor \frac{cj + c - b - 1}{a} \right \rfloor)}{2}$$

$$= \frac{1}{2}(mn(n + 1) - f(c, c - b - 1, a, m - 1) - h(c, c - b - 1, a, m - 1))$$

还要解决$h$。

H

当$a \geq c$或者$b \geq c$的时候

$$h(a, b, c, n) = (n + 1)\left \lfloor \frac{b}{c} \right \rfloor^2 + \frac{n(n + 1)(2n + 1)}{6}\left \lfloor \frac{a}{c} \right \rfloor^2 + n(n + 1)\left \lfloor \frac{b}{c} \right \rfloor\left \lfloor \frac{a}{c} \right \rfloor + h(a \mod c, b \mod c, c, n) + 2\left \lfloor \frac{a}{c} \right \rfloor g(a \mod c, b \mod c, c, n) + 2\left \lfloor \frac{b}{c} \right \rfloor f(a \mod c, b \mod c, c, n)$$

好麻烦啊……

当$a, b < c$的时候需要一些操作

$$n^2 = 2 \times \frac{n(n + 1)}{2} - n = 2\sum_{i = 1}^{n}i - n$$

可以得到

$$h(a, b, c, n) = \sum_{i = 0}^{n}(2\sum_{j = 1}^{\left \lfloor \frac{ai + b}{c} \right \rfloor}j - \left \lfloor \frac{ai + b}{c} \right \rfloor)$$

$$= 2\sum_{i = 0}^{n}\sum_{j = 1}^{\left \lfloor \frac{ai + b}{c} \right \rfloor}j - f(a, b, c, n)$$

$$= 2\sum_{j = 0}^{m - 1}(j + 1)\sum_{i = 0}^{n}[\left \lfloor \frac{ai + b}{c} \right \rfloor \geq j + 1] - f(a, b, c, n)$$

$$= 2\sum_{j = 0}^{m - 1}(j + 1)(n - \left \lfloor \frac{cj + c - b - 1}{a} \right \rfloor) - f(a, b, c, n)$$

$$= nm(m + 1) - 2g(c, c - b - 1, a, m - 1) - 2f(c, c - b - 1, a, m - 1) - f(a, b, c, n)$$

大概就是这样了。

在计算的时候如果只考虑$(a, c)$这两项的话相当于每一次把$(a, c)$变成了$(c, a \% c)$,所以时间复杂度和欧几里得算法相同,递归层数是$log$层。

时间复杂度$O(Tlogn)$。

因为递归的式子很一致,在计算的时候应当三个东西一起算比较快。

Code:

#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll; const ll P = 998244353LL; template <typename T>
inline void read(T &X) {
X = ; char ch = ; T op = ;
for (; ch > ''|| ch < ''; ch = getchar())
if (ch == '-') op = -;
for (; ch >= '' && ch <= ''; ch = getchar())
X = (X << ) + (X << ) + ch - ;
X *= op;
} template <typename T>
inline void inc(T &x, T y) {
x += y;
if (x >= P) x -= P;
} template <typename T>
inline void sub(T &x, T y) {
x -= y;
if (x < ) x += P;
} inline ll fpow(ll x, ll y) {
ll res = ;
for (; y > ; y >>= ) {
if (y & ) res = res * x % P;
x = x * x % P;
}
return res;
} namespace Likegcd {
struct Node {
ll f, g, h;
}; #define f(now) now.f
#define g(now) now.g
#define h(now) now.h const ll inv2 = fpow(, P - );
const ll inv6 = fpow(, P - ); inline Node solve(ll a, ll b, ll c, ll n) {
Node res;
if (!a) {
f(res) = (b / c) * (n + ) % P;
g(res) = (b / c) * (n + ) % P * n % P * inv2 % P;
h(res) = (b / c) * (b / c) % P * (n + ) % P;
return res;
} f(res) = g(res) = h(res) = ;
if (a >= c || b >= c) {
Node tmp = solve(a % c, b % c, c, n);
inc(f(res), (a / c) * n % P * (n + ) % P * inv2 % P);
inc(f(res), (b / c) * (n + ) % P);
inc(f(res), f(tmp)); inc(g(res), (a / c) * n % P * (n + ) % P * (( * n + ) % P) % P * inv6 % P);
inc(g(res), (b / c) * n % P * (n + ) % P * inv2 % P);
inc(g(res), g(tmp)); inc(h(res), (a / c) * (a / c) % P * n % P * (n + ) % P * (( * n + ) % P) % P * inv6 % P);
inc(h(res), (b / c) * (b / c) % P * (n + ) % P);
inc(h(res), (a / c) * (b / c) % P * n % P * (n + ) % P);
inc(h(res), h(tmp));
inc(h(res), 2LL * (a / c) % P * g(tmp) % P);
inc(h(res), 2LL * (b / c) % P * f(tmp) % P); return res;
} if (a < c && b < c) {
ll m = (a * n + b) / c;
Node tmp = solve(c, c - b - , a, m - ); f(res) = n * m % P;
sub(f(res), f(tmp)); g(res) = n * (n + ) % P * m % P;
sub(g(res), f(tmp));
sub(g(res), h(tmp));
g(res) = g(res) * inv2 % P; h(res) = n * m % P * (m + ) % P;
sub(h(res), 2LL * g(tmp) % P);
sub(h(res), 2LL * f(tmp) % P);
sub(h(res), f(res)); return res;
} return res;
} } int main() {
int testCase;
read(testCase);
for (ll a, b, c, n; testCase--; ) {
read(n), read(a), read(b), read(c);
Likegcd :: Node ans = Likegcd :: solve(a, b, c, n);
printf("%lld %lld %lld\n", ans.f, ans.h, ans.g);
}
return ;
}

Luogu 5170 【模板】类欧几里得算法的更多相关文章

  1. Solution -「Luogu 5170」类欧几里得算法

    推柿子大赛了属于是. 题目要求三个柿子,不妨分别记为: \[\begin {align} f (a, b, c, n) &= \sum \limits _{i = 0} ^{n} \lfloo ...

  2. [P5170] 类欧几里得算法

    "类欧几里得算法"第二题 P5170 [题意]已知\(n,a,b,c\),求 \[ \begin{aligned} f_{1}(a,b,c,n)&=\sum_{i=0}^n ...

  3. 模板——扩展欧几里得算法(求ax+by=gcd的解)

    Bryce1010模板 /**** *扩展欧几里得算法 *返回d=gcd(a,b),和对应等式ax+by=d中的x,y */ long long extend_gcd(long long a,long ...

  4. LOJ138 类欧几里得算法

    类欧几里得算法 给出 \(T\) 组询问,每组用 \(n, a, b, c, k_1, k_2\) 来描述.对于每组询问,请你求出 \[ \sum_{x = 0} ^ {n} x ^ {k_1} {\ ...

  5. Solution -「LOJ #138」「模板」类欧几里得算法

    \(\mathcal{Description}\)   Link.   \(T\) 组询问,每次给出 \(n,a,b,c,k_1,k_2\),求 \[\sum_{x=0}^nx^{k_1}\left\ ...

  6. BZOJ3817 Sum(类欧几里得算法)

    设$t=\sqrt r$,原题转化为$\sum_{x=1}^n(4*\lfloor\frac{tx}2\rfloor-2*\lfloor tx\rfloor+1)$考虑如何求$\sum_{x=1}^n ...

  7. 洛谷P5170 【模板】类欧几里得算法(数论)

    传送门 此题剧毒,公式恐惧症患者请直接转去代码→_→ 前置芝士 基本数论芝士 题解 本题就是要我们求三个函数的值 \[f(a,b,c,n)=\sum_{i=0}^n \left\lfloor\frac ...

  8. [BZOJ2987]Earthquake:类欧几里得算法

    分析 类欧的式子到底是谁推的啊怎么这么神仙啊orz! 简单说一下这道题,题目中的约束条件可以转化为: \[ y \leq \frac{c-ax}{b} \] 有负数怎么办啊?转化一下: \[ y \l ...

  9. 【LuoguP4433】[COCI2009-2010#1] ALADIN(含类欧几里得算法推导)

    题目链接 题意简述 区间赋值模意义下等差数列,询问区间和 \(N\leq 10^9,Q\leq 10^5\) Sol 每次操作就是把操作区间\([L,R]\)中的数赋值成: \[(X-L+1)*A\ ...

随机推荐

  1. 结合File类浅析递归的使用

    递归算法就是方法自身直接或者间接地调用到了自身,它是一种写起来很简单,但理解起来不那么简单的算法. 一个功能在被重复地调用,并且运算的结果和上一次的调用有关, 这种时候,可以使用递归. * 注意: * ...

  2. BZOJ3195: [Jxoi2012]奇怪的道路【状压DP】

    Description 小宇从历史书上了解到一个古老的文明.这个文明在各个方面高度发达,交通方面也不例外.考古学家已经知道,这个文明在全盛时期有n座城市,编号为1..n.m条道路连接在这些城市之间,每 ...

  3. 怎样创造財富?硅谷创业之父 Paul Graham 《黑客与画家》思维导图

    先送上亚马逊传送门:<黑客与画家>:硅谷创业之父 Paul Graham 文集 再送上一个思维导图: 下载大图:http://caifujianghu.com/article/ruhe-c ...

  4. 【ZedGraph】右键菜单和鼠标滚轴的移动缩放等功能的启用和禁用 (转)

    通过[ZedGraph]控件属性修改: 1.禁用右键菜单: IsShowContextMenu = false; 2.禁用鼠标滚轴移动: IsEnableHPan = false; //禁止横向移动; ...

  5. PHP 通过实现 Iterator(迭代器)接口来读取大文件文本

    读了NGINX的access日志,bnb_manage_access.log(31M) 和  bnb_wechat_access.log(50M) 附上代码: <?php /** * User: ...

  6. selenium+python 移动鼠标方法

    from selenium import webdriver from selenium.webdriver.common.keys import Keys import time driver=we ...

  7. VS2015 安装包

    http://download.microsoft.com/download/D/C/9/DC99C86F-5E93-4F77-AF7A-05AAC9BD8B72/vs2015.1.ent_chs.i ...

  8. jsp中9个隐含对象

    在JSP中一共有9个隐含对象,这个9个对象我可以在JSP中直接使用.因为在service方法已经对这个九个隐含对象进行声明及赋值,所以可以在JSP中直接使用. - pageContext 类型:Pag ...

  9. Spring MVC @ResponseBody和@RequestBody使用

    @ResponseBody用法: 作用:该注解用于将Controller的方法返回的对象,根据HTTP Request Header的Accept的内容,通过适当的HttpMessageConvert ...

  10. mkdir 权限值注意要用八进制表示,即“0”开头,而且一定不要加引号http://php.net/manual/en/function.mkdir.php