bzoj1477 && exgcd学习笔记

Posted 123456

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1477 && exgcd学习笔记相关的知识,希望对你有一定的参考价值。

exgcd

由于忘记了exgcd,这道题就没做出来。。。

exgcd的用处是求ax+by=gcd(a,b)这样方程的解

大概是这个样子的

void ext_gcd(long long a, long long b, long long &x, long long &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
    }
    else
    {
        ext_gcd(b, a % b, y, x);
        y -= x * (a / b);
    }
}
View Code

证明大概是ax+by=gcd(a,b)

根据gcd的性质bx\'+(a%b)y\'=gcd(b,a%b) 

这样就是求出了上面这个方程的解,我们要做的就是通过x\',y\'求出x,y

怎么求呢,就是把方程化回ax+by=gcd(a,b)的形式,由于gcd(a,b)=gcd(b,a%b),所以这样的解是相同的

bx\'+(a-a/b*b)y\'=c (c=gcd(b,a%b))

ay\'+b(x\'-a/b*y\')=c

那么就有x=y\',y=x\'-a/b*y\'

那么我们就先exgcd(b,a%b,y,x),这样求出了x\',y\'我们要返回x,y,由于传入了y,x,所以x=y\'已经求好了,那么就是y,现在y=x\',x=y\',那么y=x\'-a/b*y\',y=y-a/b*x,然后返回就行了

边界条件是b=0,a=...,这样就是ax+by=gcd(a,b),ax+0*y=a,那么自然可以得出x=1,y=0是一组解,顺便也求出了gcd

那么这道题可以列出方程am+y-x=an (mod l),那么移一下项,得出a(m-n)=x-y (mod l),那么相当于求(m-n)*a+b*l=x-y 的最小a的解,这不就是exgcd吗?但是x-y不是gcd(m-n,l),怎么解决呢?

我们先求出一组解,(m-n)*a\'+b*l=gcd(m-n,l) 设t=gcd(m-n,l)

如果(x-y)%t != 0那么就没有解,因为如果有一组解,那么左边的式子可以整除t,右边却不能,这很明显矛盾

所以我们对于(m-n)*a\'+b*l=gcd(m-n,l) 设t=gcd(m-n,l)得出来的解,两边同乘以(x-y)/t就是原来的那个方程了,那么把a\'和b\'同时乘以(x-y)/t就得出一组a和b了,但是这不一定是最小的,于是我们要对l/t取模,至于为什么是l/t,具体是这样的

我们可以把刚才那个方程看成一个线性同余方程,那么就是ax=b (mod n)

我们求的是最小解的间隔,这个间隔能帮我们求出最小的正整数解,设这个间隔为d,那么自然a(x+d)=b (mod n)

和ax=b (mod n)减一下就是 a*d=0 (mod n),那么我们可以知道a*d是n和a的公倍数,如果想让d最小,那么a*d应该等于lcm(a,n),a*d=lcm(a,n),因为lcm(a,n)=a*n/gcd(a,n),那么就是a*d=a*n/gcd(a,n)

d=n/gcd(a,n),就是刚才那个l/t,所以这个d和l/t就是原方程解的最小周期,取模就能求出最小解

参考http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html

http://m.blog.csdn.net/LiRewriter/article/details/76762084

Ax+By=C

当C%gcd(a,b)==0有解

A,B,C不管正负

通解:x=x0+bt,y=yo-at

最小正整数解:t=b/gcd(a,b) x=(x%t+t)%t

方程axc(mod b)ax+by=c

求逆元:ax=1(mod b)

相当于求ax+by=1 最小正整数解:x+b*b/gcd(a,b)

#include<bits/stdc++.h>
using namespace std;
long long x, y, m, n, l;
void ext_gcd(long long a, long long b, long long &x, long long &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
    }
    else
    {
        ext_gcd(b, a % b, y, x);
        y -= x * (a / b);
    }
}
int main()
{
    scanf("%lld%lld%lld%lld%lld", &x, &y, &m, &n, &l);
    if(m < n)
    {
        swap(n, m);
        swap(x, y);
    }
    long long delta_v = m - n, delta_d = ((y - x) % l + l) % l, t = __gcd(delta_v, l), a, b;
    if(delta_d % t != 0)
    {
        puts("Impossible");
        return 0;
    }
    ext_gcd(delta_v, l, a, b);
//    printf("a=%lld t=%lld delta_d=%lld\\n", a, t, delta_d);
    l /= t;
    a *= delta_d / t;
    a = (a % l + l) % l;
    printf("%lld", a);
    return 0;
}
View Code

 

  

以上是关于bzoj1477 && exgcd学习笔记的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1477: 青蛙的约会(exgcd)

bzoj 1477: 青蛙的约会exgcd

BZOJ1477: 青蛙的约会

bzoj1477: 青蛙的约会

splay专题复习——bzoj 3224 &amp; 1862 &amp; 1503 题解

二项式定理&反演证明&bzoj2839集合计数题解