首页 > 编程语言 >类欧几里得算法

类欧几里得算法

时间:2023-02-03 17:35:53浏览次数:28  
标签:lfloor right frac 欧几里得 rfloor 算法 mod left

我还是觉得我学这玩意纯属闲着没事干。

类欧几里得算法

定义

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

让你 \(O(\log n)\) 计算这个东西。

首先假如 \(a\ge c\) 或 \(b\ge c\) 我们显然可以把它们对 \(c\) 取模后加上什么东西。推一下式子。

设 \(a'=a\bmod c,b'=b\bmod c\)。

\[\begin{aligned} f(a,b,c,n)=&\sum_{i=0}^n\left\lfloor\frac{ai+b}c\right\rfloor\\ =&\sum_{i=0}^n\left\lfloor\frac{(\lfloor\frac ac\rfloor c+a')i+\lfloor\frac bc\rfloor c+b'}c\right\rfloor\\ =&\sum_{i=0}^n\left\lfloor\frac ac\right\rfloor i+\left\lfloor\frac bc\right\rfloor+\left\lfloor\frac{a'i+b'}{c}\right\rfloor\\ =&\left\lfloor\frac ac\right\rfloor\frac{n(n+1)}2+\left\lfloor\frac bc\right\rfloor(n+1)+f(a',b',c,n) \end{aligned} \]

然后考虑 \(a<c,b<c\) 的情况怎么搞。以下是这类长的像类欧的东西怎么推的大概套路。

\[\begin{aligned} f(a,b,c,n)=&\sum_{i=0}^n\left\lfloor\frac{ai+b}c\right\rfloor\\ =&\sum_{i=0}^n\sum_{j=0}^{\left\lfloor\frac{ai+b}c\right\rfloor-1}1\\ =&\sum_{j=0}^{\lfloor\frac{an+b}c\rfloor-1}\sum_{i=0}^n\left[j<\left\lfloor\frac{ai+b}c\right\rfloor\right] \end{aligned} \]

把后边的拆一下:

\[\begin{aligned} &\left[j<\left\lfloor\frac{ai+b}c\right\rfloor\right]\\ =&\left[j+1\le\left\lfloor\frac{ai+b}c\right\rfloor\right]\\ =&\left[j+1\le\frac{ai+b}c\right]\\ =&[jc+c\le ai+b]\\ =&[jc+c-b-1<ai]\\ =&\left[i>\left\lfloor\dfrac{jc+c-b-1}a\right\rfloor\right] \end{aligned} \]

代入原式:

\[\begin{aligned} &\sum_{j=0}^{\lfloor\frac{an+b}c\rfloor-1}\sum_{i=0}^n\left[i>\left\lfloor\dfrac{jc+c-b-1}a\right\rfloor\right]\\ =&\sum_{j=0}^{\lfloor\frac{an+b}c\rfloor-1}\left(n-\left\lfloor\dfrac{jc+c-b-1}a\right\rfloor\right)\\ =&n\left\lfloor\frac{an+b}c\right\rfloor-f(c,c-b-1,a,\left\lfloor\frac{an+b}c\right\rfloor-1) \end{aligned} \]

发现这里分母 \(c\) 和分子 \(a\) 互换,可以继续取模向下递归。终止条件当 \(a=0\) 时 \(f(a,b,c,n)=n\left\lfloor\dfrac bc\right\rfloor\)。

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

然后继续推板子的另外两个式子:

\[g(a,b,c,n)=\sum_{i=0}^ni\left\lfloor\dfrac{ai+b}c\right\rfloor \]

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

g

先看 \(a,b\) 对 \(c\) 取模后的变化。以下均设 \(a'=a\bmod c,b'=b\bmod c,m=\left\lfloor\dfrac{an+b}c\right\rfloor,t=\left\lfloor\dfrac{jc+c-b-1}a\right\rfloor\)。

\[\begin{aligned} g(a,b,c,n)=&\sum_{i=0}^ni\left\lfloor\frac{ai+b}c\right\rfloor\\ =&\sum_{i=0}^ni\left\lfloor\frac{(\lfloor\frac ac\rfloor c+a')i+\lfloor\frac bc\rfloor c+b'}c\right\rfloor\\ =&\sum_{i=0}^n\left\lfloor\frac ac\right\rfloor i^2+\left\lfloor\frac bc\right\rfloor i+\left\lfloor\frac{a'i+b'}c\right\rfloor\\ =&\left\lfloor\frac ac\right\rfloor\frac{n(n+1)(2n+1)}6+\left\lfloor\frac bc\right\rfloor\frac{n(n+1)}2+g(a',b',c,n) \end{aligned} \]

\[\begin{aligned} g(a,b,c,n)=&\sum_{i=0}^ni\left\lfloor\frac{ai+b}c\right\rfloor\\ =&\sum_{i=0}^ni\sum_{j=0}^{\lfloor\frac{ai+b}c\rfloor}1\\ =&\sum_{j=0}^{m-1}\sum_{i=0}^ni\left[i<\left\lfloor\frac{ai+b}c\right\rfloor\right]\\ =&\sum_{j=0}^{m-1}\sum_{i=0}^ni[i>t]\\ =&\sum_{j=0}^{m-1}\frac{(n+t+1)(n-t)}2\\ =&\frac 12\left(mn(n+1)-h(c,c-b-1,a,m-1)-f(c,c-b-1,a,m-1)\right) \end{aligned} \]

h

\[\begin{aligned} h(a,b,c,n)=&\sum_{i=0}^n\left\lfloor\frac{ai+b}c\right\rfloor^2\\ =&\sum_{i=0}^n\left\lfloor\frac{(\lfloor\frac ac\rfloor c+a')i+\lfloor\frac bc\rfloor c+b'}c\right\rfloor^2\\ =&\sum_{i=0}^n\left(\left\lfloor\frac ac\right\rfloor i+\left\lfloor\frac bc\right\rfloor +\left\lfloor\frac{a'i+b'}c\right\rfloor\right)^2\\ =&\sum_{i=0}^n\left(\left\lfloor\frac ac\right\rfloor i\right)^2+\left\lfloor\frac bc\right\rfloor^2+\left\lfloor\frac{a'i+b'}c\right\rfloor^2+2\left\lfloor\frac ac\right\rfloor\left\lfloor\frac bc\right\rfloor i+2\left\lfloor\frac ac\right\rfloor\left\lfloor\frac{a'i+b'}c\right\rfloor+2\left\lfloor\frac bc\right\rfloor\left\lfloor\frac{a'i+b'}c\right\rfloor\\ =&h(a',b',c,n)+2\left\lfloor\frac bc\right\rfloor f(a',b',c,n)+2\left\lfloor\frac ac\right\rfloor g(a',b',c,n)+\\ &\left\lfloor\frac ac\right\rfloor^2\frac{n(n+1)(2n+1)}6+\left\lfloor\frac bc\right\rfloor^2(n+1)+\left\lfloor\frac ac\right\rfloor\left\lfloor\frac bc\right\rfloor n(n+1) \end{aligned} \]

首先可以把 \(n^2\) 化为

\[2\dfrac{n(n+1)}2-n=2\sum_{i=0}^ni-n \]

来避免化简的时候出现两个求和号相乘。

\[\begin{aligned} h(a,b,c,n)=&\sum_{i=0}^n\left\lfloor\frac{ai+b}c\right\rfloor^2\\ =&\sum_{i=0}^n\left(2\sum_{j=0}^{\lfloor\frac{ai+b}c\rfloor}j-\left\lfloor\frac{ai+b}c\right\rfloor\right)\\ =&2\sum_{i=0}^n\sum_{j=1}^{\lfloor\frac{ai+b}c\rfloor}j-f(a,b,c,n) \end{aligned} \]

看前面一半:

\[\begin{aligned} &\sum_{i=0}^n\sum_{j=1}^{\lfloor\frac{ai+b}c\rfloor}j\\ =&\sum_{i=0}^n\sum_{j=0}^{\lfloor\frac{ai+b}c\rfloor-1}j+1\\ =&\sum_{j=0}^{m-1}(j+1)\sum_{i=0}^n\left[j<\left\lfloor\frac{ai+b}c\right\rfloor\right]\\ =&\sum_{j=0}^{m-1}(j+1)(n-t)\\ =&\frac 12nm(m+1)-\sum_{j=0}^{m-1}(j+1)t\\ \end{aligned} \]

所以有

\[h(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) \]

这三个可以一块算。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
const int mod=998244353,inv2=499122177,inv6=166374059;
int n,a,b,c;
struct node{
    int f,g,h;
    node(){f=g=h=0;}
};
node solve(int a,int b,int c,int n){
    node ans;
    int m=(1ll*a*n+b)/c,ac=a/c%mod,bc=b/c%mod;
    if(!a){
        ans.f=1ll*bc*(n+1)%mod;
        ans.g=1ll*n*(n+1)%mod*inv2%mod*bc%mod;
        ans.h=1ll*bc*bc%mod*(n+1)%mod;
        return ans;
    }
    if(a>=c||b>=c){
        ans.f=(1ll*n*(n+1)%mod*inv2%mod*ac%mod+1ll*(n+1)*bc%mod)%mod;
        ans.g=(1ll*n*(n+1)%mod*(2*n+1)%mod*inv6%mod*ac%mod+1ll*n*(n+1)%mod*inv2%mod*bc%mod)%mod;
        ans.h=(1ll*n*(n+1)%mod*(2*n+1)%mod*inv6%mod*ac%mod*ac%mod+
                1ll*(n+1)*bc%mod*bc%mod+
                1ll*n*(n+1)%mod*ac%mod*bc%mod)%mod;
        node d=solve(a%c,b%c,c,n);
        ans.f=(ans.f+d.f)%mod;
        ans.g=(ans.g+d.g)%mod;
        ans.h=(ans.h+d.h+2ll*bc%mod*d.f%mod+2ll*ac%mod*d.g%mod)%mod;
        return ans;
    }
    node d=solve(c,c-b-1,a,m-1);
    ans.f=(1ll*n*m%mod-d.f+mod)%mod;
    ans.g=(1ll*n*(n+1)%mod*m%mod-d.h-d.f+mod+mod)%mod*inv2%mod;
    ans.h=(1ll*n*m%mod*(m+1)%mod-2ll*d.g%mod-2ll*d.f%mod-ans.f+3ll*mod)%mod;
    return ans;
}
signed main(){
    int tim;scanf("%lld",&tim);
    while(tim--){
        scanf("%lld%lld%lld%lld",&n,&a,&b,&c);
        node ans=solve(a,b,c,n);
        printf("%lld %lld %lld\n",ans.f,ans.h,ans.g);
    }
    return 0;
}

下面是几个题。

P5171 Earthquake

大板板题。题意是求这个:

\[\sum_{x=0}^{\lfloor\frac ca\rfloor}\left\lfloor\frac{-ax+c}b\right\rfloor+1 \]

上边挂个负数没法类欧,那假设 \(b>a\) (如果相反可以交换),那么加一个 \(x\) 减一个 \(x\) 有:

\[\sum_{x=0}^{\lfloor\frac ca\rfloor}\left\lfloor\frac{(b-a)x+c}b\right\rfloor-x+1 \]

算就行了。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define int long long
using namespace std;
int n,a,b,c;
int f(int a,int b,int c,int n){
    if(!a)return b/c*(n+1);
    int ans=0;
    if(a>=c||b>=c){
        ans=n*(n+1)/2*(a/c)+(n+1)*(b/c)+f(a%c,b%c,c,n);
        return ans;
    }
    int m=(a*n+b)/c;
    int d=f(c,c-b-1,a,m-1);
    ans=n*m-d;
    return ans;
}
signed main(){
    scanf("%lld%lld%lld",&a,&b,&c);
    if(a>b)swap(a,b);
    printf("%lld\n",f(b-a,c,b,c/a)-(c/a)*(c/a+1)/2+c/a+1);
    return 0;
}

[COCI2009-2010#1] ALADIN

首先这题我没写纯口胡的。因为这题线段树还 tm 要离散化而且恶意卡空间(动态开点容易 MLE,空间 64MB 时间 8s 然而基本最大的点都是 1s 过的)我不知道什么意味。

首先关于这个修改操作,线段树每个节点可以记录一个 \(L,A,B\),这样这个区间的和就可以类欧算。线段树查询就正常查就行了。然而代码不是一般的恶心。复杂度 \(O(q\log^2n)\)。

万能欧几里得到时候再说。

标签:lfloor,right,frac,欧几里得,rfloor,算法,mod,left
From: https://www.cnblogs.com/gtm1514/p/17089991.html

相关文章

  • 基于DNN深度学习网络的OFDM信号检测算法的matlab仿真,对比LS和MMSE两个算法
    1.算法描述在OFDM系统中,信道估计器的设计上要有两个问题:**一是导频信息的选择,由于无线信道的时变特性,需要接收机不断对信道进行跟踪,因此导频信息也必须不断的传送:二是......
  • 算法
    /*1.字符串最后一个单词的长度*/stringstr;getline(cin,str);intcount=0;intlen=str.length();for(inti=len-1;i>-1;i--)......
  • 最大公约数算法真的无趣?一看就会的算法代码示例
    最大公约数算法不是很无聊,计算最大公约数是数学中一个重要的概念,可以用于判断两个数是否互质、求分数的约分等,在很多领域都有广泛的应用。具体如下:判断两个数是否互质:两......
  • LeetCode刷题,代码随想录算法训练营Day3| 链表理论基础 203.移除链表元素 707.设计链
    链表理论基础链表是通过指针串联在一起的线性结构,每个节点由一个数据域和一个指针域构成。链表的类型单链表双链表有两个指针域,一个指向下一个节点,一个指向上一个节......
  • 【算法训练营day39】LeetCode62. 不同路径 LeetCode63. 不同路径II
    LeetCode62.不同路径题目链接:62.不同路径独上高楼,望尽天涯路第一次接触二维的dp数组,初始化会麻烦一点,dp数组表示的是机器人移动到第i行第j列格子的所有路径数。class......
  • 扩展欧几里得(exgcd)
    这里先说一下最大公约数怎么求,辗转相除法都会用,这里讲一下站桩相除法的原理。例如两个数假设这两个数大小,设是这两个数的最大公约数。可得因为这里都是一个正整数不会对最......
  • ST算法(区间最值)
    ST算法是解决RMQ(区间最值)问题,它能在O(nlogn)的时间预处理,然后酶促查询的复杂度是O(1)。其原理是倍增,f[i][j]表示从i位起的2^j个数中的最大数,即[i,i+2^j-1]中的最大值。首先,我们......
  • 机器学习——k-近邻算法(KNN)、
    k-近邻算法(kNN),它的工作原理是:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新......
  • 6.2RLE算法的机制
    数据后,不难看出有不少字符是重复出现的。在字符后面加上重复出现次数,AAAAAABBCDDEEEEEF就可以用A6B2C1D2E5F1来表示。A6B2CID2E5F1是12个字符也就是12字节,因此结果就将原文......
  • 算法--2023.2.2
    1.力扣72--编辑距离classSolution{//典型动态对话问题publicintminDistance(Stringword1,Stringword2){intm=word1.length(),n=word2.......