类欧几里得算法

定义

这个算法用于求一条直线下整点个数,我们定义

F(a,b,c,n)=i=0nai+bc

其他几个乘系数的扩展不想学了TAT

推导

acbc

acbc 时,我们考虑把分子对 c 的商和余数分别提出来,那么有

F(a,b,c,n)=i=0n(((amodc)i+(bmodc)c)i+aci+bc)=F(amodc,bmodc,c,n)+n(n+1)2ac+(n+1)bc

a<cb<c

a<cb<c 时,用几何意义转化为一条直线与 xy 轴以及 x=n 围成直角梯形内的整点个数。

设上界 m=an+bc ,那么我们考虑拆式子

F(a,b,c,n)=i=0nj=1m[ai+bcj]=i=0nj=0m1[ai+bcj+1]=i=0nj=0m1[(ai+bc)j+1]=i=0nj=0m1[aijc+cb]=i=0nj=0m1[ijc+cba]

很多地方都可以舍掉取整,因为整数和分数比较大小(考虑等于)的时候可以忽略下取整。

考虑分子减 1 换成 > 并交换和式:

F(a,b,c,n)=i=0nj=0m1[i>jc+cb1a]=j=0m1i=0n[i>jc+cb1a]=j=0m1(njc+cb1a)=nmj=0m1jc+cb1a=nmF(c,cb1,a,m1)

然后我们就可以递归处理了。

复杂度证明

我们只观察 ac 两位,如果 a>c 那么 amodc ,否则交换 ac

那么复杂度其实和扩展欧几里得算法是一样的 O(logn)

代码

f 还是比较短的。

ll f(ll a, ll b, ll c, ll n) { if (!a) return b / c * (n + 1); if (a >= c || b >= c) return f(a % c, b % c, c, n) + (a / c) * n * (n + 1) / 2 + (b / c) * (n + 1); ll m = (a * n + b) / c; return n * m - f(c, c - b - 1, a, m - 1); }

__EOF__

本文作者zjp_shadow
本文链接https://www.cnblogs.com/zjp-shadow/p/10601728.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zjp_shadow  阅读(1329)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示