【题解】类欧几里得算法

题面

,要求 级别的时间解决。

通常

洛谷模版链接:https://www.luogu.com.cn/problem/P5170

解析

(1)当

可以理解为 先单独处理,分别从每个 中拿出所有 也单独处理。

再将 剩下的和 加起来

(2)当

,代表循环内下取整可以取到的最大整数。

上面这句话的意思:当 时,所有 都会被计入 1。

也就是说一个 ,会被计入 次,求出的值和原式相同。

分析 Iverson 括号的内部条件,

这样我们就得到了和 有关的约束,原式变为:

将求和下标平移 ,将原式变成符合 函数的形式:

(1)当

(2)当

这两种变换使参数 变为 ,与欧几里得算法的辗转相除结构一致,从而保证 的时间复杂度。

派生形式

函数的推导

(1)当

(2)当

,代表循环内下取整可以取到的最大整数。

,则原式为:

又因为:

所以,原式为:

函数的推导

(1)当

,则有:

所以原式为:

(2)当

因为 ,则原式为:

,设

将求和下标平移 ,将原式变成符合 函数的形式:

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;

typedef long long LL;
const LL P = 998244353;
LL i2 = 499122177, i6 = 166374059;   // 逆元

struct node {
    LL f, g, h;
};

node dfs(LL a, LL b, LL c, LL n) {
    if (n < 0) return {0, 0, 0};
    node res;
    LL qa = a / c, qb = b / c, ra = a % c, rb = b % c;
    if (a == 0) {
        res.f = (n + 1) * qb % P;
        res.g = n * (n + 1) % P * i2 % P * qb % P;
        res.h = (n + 1) * qb % P * qb % P;
    }
    else if (a >= c || b >= c){
        node no = dfs(ra, rb, c, n);
        res.f = (no.f + n * (n + 1) % P * i2 % P * qa % P + (n + 1) * qb % P) % P;
        res.g = (no.g + n * (n + 1) % P * (2 * n + 1) % P * i6 % P * qa % P
            + n * (n + 1) % P * i2 % P * qb % P) % P;
        res.h = (no.h + 2 * qa % P * no.g % P + 2 * qb % P * no.f % P +
            n * (n + 1) % P * (2 * n + 1) % P * i6 % P * qa % P * qa % P +
            n * (n + 1) % P * qa % P * qb % P + (n + 1) * qb % P * qb % P) % P;
    }
    else if (n == 0) {
		res.f = qb;
		res.g = 0;
		res.h = qb * qb % P;
	}
    else {
        LL m = (a * n + b) / c;
        node no = dfs(c, c - b - 1, a, m - 1);
        res.f = ((n * m % P - no.f) % P + P) % P;  
        LL term1 = m % P * n % P * (n + 1) % P * i2 % P;
        LL term2 = (no.f + no.h) % P * i2 % P;
        res.g = (term1 - term2 + P) % P;
        res.h = (n % P * m % P * (m + 1) % P
            - (2 * no.g) % P 
            - (2 * no.f) % P 
            - res.f + 4 * P) % P;
    }
    return res;
}

int main () {
    ios::sync_with_stdio(false);
    cin.tie(0);

    int T;
    cin >> T;
    while (T --) {
        LL a, b, c, n;
        cin >> n >> a >> b >> c;
        node ans = dfs(a, b, c, n);
        cout << ans.f << " " << ans.h << " " << ans.g << "\n";
    }

    return 0;
}
相关推荐
小程故事多_804 小时前
从A2C、TRPO、PPO到GRPO,强化学习策略梯度算法完整演进与大模型落地实战解析
人工智能·算法
2601_956121976 小时前
二分算法(知识点+题目)
c++·算法
蒙奇·D·路飞-8 小时前
OpenClaw:开源的《合金弹头》精神续作与终极本地部署指南
c++·开源·mfc
AndrewHZ8 小时前
【LLM技术全景】阶段总结:技术原理篇核心知识回顾
人工智能·深度学习·算法·语言模型·大模型·llm·芯片开发
小星星闪亮登场9 小时前
2026萌新联赛第三场-- (郑州轻工业大学)
数据结构·c++·经验分享·算法·贪心算法·排序算法·深度优先
梓䈑10 小时前
【用 Vibe Coding 实现的 C++17 在线判题系统】前端开发 + Web 自动化测试
前端·c++·ai编程
冻柠檬飞冰走茶10 小时前
PTA基础编程题目集 7-8超速判断(C++语言实现)
开发语言·数据结构·c++·算法
玖玥拾10 小时前
LeetCode 88 合并两个有序数组
算法·leetcode
TunerT_TQ10 小时前
Valhalla 静态工程审阅 #018|MMCV 源码证据驱动评测【大厂开源基础设施特辑】
c++·开源·mfc·#计算机视觉·#商汤科技·#openmmlab·#静态源码审计
数据皮皮侠AI10 小时前
上市公司数字供应链金融指数(2010-2024)
大数据·人工智能·算法