• 类欧几里得算法浅谈(部分)


    ###学习类欧几里得算法,因为是蒟蒻,感觉网上很多都看不懂,所以自己写一篇快活快活

    第一类求和式:

    (F(a,b,c,n)=sum_{i=0}^nlfloorfrac{a*i+b}{c} floor)


    对于这样形式的求和,我们有以下的推导:

    1.当(a>=c)(b>=c)时,我们有:

    对于(lfloorfrac{a}{c} floor),

    它实际等价于(lfloorfrac{amod c}{c} floor+lfloorfrac{a}{c} floor),

    于是对于原先的式子,我们可以推出:

    (F(a,b,c,d,n)=sum_{i=0}^nlfloorfrac{a*i+b}{c} floor) =(sum_{i=0}^n(lfloorfrac{amod c*i+bmod c}{c} floor+lfloorfrac{a*i}{c} floor+lfloorfrac{b}{c} floor))

    进一步化为递归的形式就是:

    (F(a\%c,b\%c,c,n)+frac{(n+1)n}{2}*lfloorfrac{a}{c} floor+(n+1)*lfloorfrac{b}{c} floor)

    2.当(a<c)(b<c)时我们有:

    我们观察可以很容易的发现,原先的和式的右边一大堆,去掉下取整实际上表示出来就是一条直线,即:

    (F=kx+b),((k=frac{a}{c},b=frac{b}{c})),

    然后我们就可以轻轻松松的画出一个一次函数的图像,在坐标系里表现出的就是一个直角梯形,函数的定义域(Din[0,n]),函数的值域(Zin[b,m]),其中令(m=frac{a*n+b}{c}),也就是当(i)等于(n)时的值.我们要求定义域内函数值的和,自然就是求积分,也就是这个直角梯形的面积.然后加上下整除符号,我们需要求出的就是这个梯形内整点的个数.

    我们枚举所有整点的纵坐标,就有:

    (F=sum_{i=0}^{n}sum_{j=1}^{m}[lfloorfrac{a*i+b}{c} floor>=j])

    (=sum_{i=0}^{n}sum_{j=0}^{m-1}[lfloorfrac{a*i+b}{c} floor>=j+1])

    对于:

    ([lfloorfrac{a*i+b}{c} floor>=j+1]),

    我们知道,大于等于去掉下整除依旧成立,于是

    (=sum_{i=0}^{n}sum_{j=0}^{m-1}[(frac{a*i+b}{c})>=j+1])

    将分母乘过去,(b)移过去:

    (=sum_{i=0}^{n}sum_{j=0}^{m-1}[a*i>=j*c+c-b])

    (a)除过去:

    (=sum_{i=0}^{n}sum_{j=0}^{m-1}[i>=frac{(j*c+c-b)}{a}])

    我们注意到,(j)的变化与(i)是无关的,于是我们可以将两个(sum)交换

    (=sum_{j=0}^{m-1}sum_{i=0}^{n}[i>=frac{(j*c+c-b)}{a}])

    (=sum_{j=0}^{m-1}sum_{i=0}^{n}[i>frac{(j*c+c-b-1)}{a}])

    (分子减一,去掉等号)

    去掉内层(sigma):

    (=sum_{j=0}^{m-1} n-frac{(j*c+c-b-1)}{a})

    (这个显然等价)

    (=n*m-sum_{j=0}^{m-1} frac{(j*c+c-b-1)}{a})

    老规矩,转换成递归形式:

    (=n*m-F(c,c-b-1,a,m-1))

    (code:)

    
    inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b; } 
    inline int sub(int a,int b){return a-b<0?a-b+mod:a-b;} 
    inline int mul(ll a,ll b){return a*b<mod?a*b:a*b>=(mod<<1)?a*b%mod:a*b-mod;}
    
    int likegcd(int a,int b,int c,int n) 
    { 
        if (!a) return 0; 
        if (a>=c||b>=c) { 
            int tmp=likegcd(a%c,b%c,c,n); 
            tmp=add(add(tmp,mul(mul(mul(n,n+1),inv[2]),a/c)),mul(n+1,b/c)); 
            return tmp; 
        } 
        // ll m=((ll)a*n+((ll)b)/(ll)c); 
        int f=(((ll)a*n)+b)/c; 
        // prllf("[%lld]",f%mod); 
        return sub(mul(n,f),likegcd(c,c-b-1,a,f-1)); 
    }
    
    

    (完)


    (待补)

  • 相关阅读:
    syslog
    setting-url配置
    计划任务_crontab
    css
    git之一: git基础
    LeetCode 第 151 场周赛
    LeetCode 第 149 场周赛
    LeetCode 第 150 场周赛
    【解决方案】SpringCloud项目优雅发版、部署
    NAT(地址转换技术)学习
  • 原文地址:https://www.cnblogs.com/KatouKatou/p/9745998.html
Copyright © 2020-2023  润新知