zoukankan      html  css  js  c++  java
  • 类欧几里得算法

    类欧几里得

    (e.g.)(sumlimits_{x=1}^nA^xB^{lfloorfrac{ax+b}{c} floor})

    • 把柿子转化成一个操作序列,对于一条直线(左上到右下),碰到一条(y=n) 的横线进行一次操作U,碰到一条(x=n)的竖线进行一次操作(R),碰到整点进行一次操作(UR)。两个操作序列合并就是把前一个的贡献加到后一个序列的答案里(有点像cdq分治?),需要信息支持快速合并。

    • 还是看例子:

      • 初始化:(curA=I,curB=I,sum=0)

      • 两个操作是 (U:curB*=B R:curA*=A,sum+=curA*curB)

      • 合并两个序列(x,y)(x)(y)后),相当于序列(y)的初始化变成了 (curA=x.curA,curB=x.curB)

        那么(ans.curA=x.curA*y.curA, ans.curB=x.curB*y.curB, ans.sum=x.sum+x.curA*y.sum*x.curB)

    具体过程

    设函数(solve(n,a,b,c,A,B))

    表示值域为(n),直线为(y=lfloor frac{ax+b}{c} floor)横坐标+1填一个(B)操作序列,纵坐标+1填一个(A)操作序列。(A,B)从1开始标号。

    可以得到:共有(n)(B),第(i)(B)前面共有(lfloor frac{ai+b}{c} floor)(A)

    每次进行以下操作

    1. (a->a\%c,b->b\%c)

      • (e.g.) (solve(3,5,1,3,A,B)->solve(3,2,1,3,A',B'))

        (AABABAAB->ABBAB)

      • (a\%=c)带来的变化:(B'=A^{aover c}B)

      • (b\%=c)无影响:

        • (i>1)时,考虑第(i)(B)和第(i-1)(B),他们两个之间的(A)(lfloorfrac{ai+b}{c} floor-lfloorfrac{a(i-1)+b}{c} floor=lfloor{aover c} floor)个,所以(b\%=c)无影响
        • 如果(i=1)(B)前面就有(lfloorfrac{a+b}{c} floor)(A),看起来(b%=c)是有影响的,但是因为操作过程中的处理,也可以把他变成无影响(具体见下)
    2. 考虑递归下去,((A,B)->(B,A))

      • 推导:考虑第(x)(A)和其之后第一个(B),假设是序列中的第(y)(B)(推的时候因为x,y为整数,所以一些向上向下取整是可以直接加或者直接去的)

        (i)(B)之前共有(lfloorfrac{ai+b}{c} floor)(A)

        [xle lfloorfrac{ay+b}{c} floor ]

        [xle frac{ay+b}{c} ]

        [frac{cx-b}{a}le y ]

        [lceilfrac{cx-b}{a} ceille y ]

        [lfloorfrac{cx-b+a-1}{a} floorle y ]

        [lfloorfrac{cx-b-1}{a} floor< y ]

        所以第(i)(A)之前共有(lfloorfrac{ci-b-1}{a} floor)(B)

      • (i=0)时,(lfloorfrac{ci-b-1}{a} floor<0),所以要特殊考虑第一个(A),具体做法是(lfloorfrac{ci-b-1}{a} floor->lfloorfrac{c(i+1)-b-1}{a} floor)(A)从0开始标号,然后再把第1个(A)(即现在的第0个(A))和它之前的(B)提出来

      • 最后一个(A)之后的(B)也要特殊考虑

      • (m=lfloor frac{a*n+b}{c} floor,cnt=n-lfloorfrac{c*m-b-1}{a} floor)(A)的数量,最后一个(A)之后的(B)的数量),

        (solve(n,a,b,c,A,B)-> B^{lfloorfrac{c-b-1}{a} floor}+A+solve(m-1,c,c-b-1,a,B,A)+B^{cnt})

    3. 第一次进入递归的时候要先把((a*0+b)/c)(A)的影响提出来,而后面因为每次都提出了第一个(A)及其之前的(B),所以相当于把每次((a*0+b)/c)的影响提出来了,所以递归的时候可以直接(b\%=c)

  • 相关阅读:
    [C++知识点]2015.4.18
    [COCOS2DX]第一个开源项目的部署和运行<win32版本>
    [COCOS2DX]交叉编译实践+速度优化(vs2012修改win32代码+修改makefile+编译安卓项目包+部署安卓项目包到Eclipse+运行apk)
    [COCOS2DX]COCOS命令新建项目+编译安卓项目并成功运行
    [COCOS2DX]官网helloworld在VS2012中的部署
    【转】int const A::func()和int A::func() const
    【转】Singleton单例模式
    【转】java静态代码块和构造方法执行顺序
    小程序加入阿拉丁统计
    关于固定footer的用法
  • 原文地址:https://www.cnblogs.com/fruitea/p/12408849.html
Copyright © 2011-2022 走看看