数学#扩展欧几里德 POJ 1061&2115&2891

寒假做的题了,先贴那时写的代码。

POJ 1061

#include<iostream>
#include<cstdio>
typedef long long LL;
using namespace std;

void extend_gcd(LL a,LL b,LL &d,LL &x,LL &y)
{
    if(b==0)
    {
        d=a;
        x=1,y=0;
    }
    else
    {
        extend_gcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}

int main()
{
    LL x,y,m,n,L;
    while(scanf("%I64d%I64d%I64d%I64d%I64d",&x,&y,&m,&n,&L)!=EOF)
    {
        LL d,xx,yy;
        extend_gcd(n-m,L,d,xx,yy);
        if((x-y)%d==0)
        {
            LL p=L/d;
            xx=(x-y)/d*xx;
            xx=(xx%p+p)%p;
            printf("%I64d\n",xx);
        }
        else printf("Impossible\n");
    }
    return 0;
}


POJ 2115

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<cstdlib>
#include<vector>
#include<stack>
#include<map>
using namespace std;
typedef long long ll;

ll extend_gcd(ll a,ll b,ll &x,ll &y)
{  //return d=gcd(a,n);
    if(b==0)
    {
        x=1,y=0;
        return a;
    }
    else
    {
        ll t=extend_gcd(b,a%b,x,y);
        ll xx=x,yy=y;
        x=yy;
        y=xx-(a/b)*yy;
        return t;
    }
}

int main()
{
    ll A,B,C,k,x,y;
    while(~scanf("%I64d %I64d %I64d %I64d",&A,&B,&C,&k))
    {
        if(A==0&&B==0&&C==0&&k==0)  break;
        ll a=C,b=B-A,n=(ll)1<<k; //n=2^k
        ll d=extend_gcd(a,n,x,y);

        if(b%d!=0) //方程无解
            printf("FOREVER\n");
        else
        {
            x=(x*(b/d))%n;  //x为方程ax=b(mod n)的最小解
            x=(x%(n/d)+n/d)%(n/d);  //x为方程ax=b(mod n)的最小整数解
            printf("%I64d\n",x);
        }
    }
    return 0;
}


POJ 2891

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;

void extend_gcd(ll a,ll b,ll &d,ll &x,ll &y)
{
    if(b==0)
    {
        d=a;
        x=1,y=0;
    }
    else
    {
        extend_gcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}

int main()
{
    int k;
    ll a1,r1,a,r;
    while(~scanf("%d",&k))
    {
        scanf("%I64d%I64d",&a1,&r1);
        int flag=1;
        for(int i=2;i<=k;i++)
        {
            scanf("%I64d%I64d",&a,&r);
            ll d,x,y;
            extend_gcd(a1,a,d,x,y);
            if((r-r1)%d!=0)
                flag=0;
            ll p=a/d;
            x=(r-r1)/d*x;
            x=(x%p+p)%p;
            r1=a1*x+r1;
            a1=a1*(a/d);
        }
        if(flag)
            printf("%I64d\n",r1);
        else printf("-1\n");
    }
    return 0;
}
时间: 2024-10-16 10:22:22

数学#扩展欧几里德 POJ 1061&2115&2891的相关文章

拓展欧几里得详解 及其题目 POJ 1061 2115 2142 UVA 10673 10090

最近做了一些拓展欧几里得的题目呢,嘛,从一开始的不会到现在有点感觉,总之把我的经验拿出来和大家分享一下吧. 普通的欧几里得是用于解决求两个数a,b的gcd的,但是我们知道,gcd是线性组合 { ax+by | x,y∈Z }里的最小正元素(什么?不知道怎么来的?好吧...算法导论里数论算法那一章有证明),假若我们能够把这个x和y找出来,那么可以用来解决很多问题. (以下的gcd和lcm均指(gcd(a,b)和lcm(a,b)) 首先,假设ax+by=gcd这一个方程有一个特解x*,y*.那么显然

POJ 1061青蛙的约会(扩展欧几里德)

对欧几里德不太熟悉,参考了网上的一些讲解又学习了一下 利用扩展欧几里德算法求线性方程的一般过程:a*x + b*y = m 令a1 = a/gcd(a,b) b1 = b/gcd(a,b) m1 = m/gcd(a,b) a*x + b*y = m两边同除以m1a*x/m1 + b*y/m1 = m/m1 = gcd(a,b)设x1 = x/m1 ,y1 = y/m1 则原式变为a*x1 + b*y1 = gcd(a,b)若求出这个方程中的x1,y1,那么x = x1*m1, y = y1*m1

poj 1061 青蛙约会(扩展欧几里德)

题目链接: http://poj.org/problem?id=1061 题目大意: 中文题目,题意一目了然,就是数据范围大的出奇. 解题思路: 假设两只青蛙都跳了T次,可以列出来不定方程:p*l + (n-m)*T == x - y.列出等式以后,利用扩展欧几里德计算不定方程的解.在求出整数最小解的地方卡了好久,好久. 想具体了解扩展欧几里德的用法和证明的话,可以看一下神牛的博文,我自认弱绞尽脑汁也写不来这么好,附上链接:http://www.cnblogs.com/frog112111/ar

ACM: POJ 1061 青蛙的约会 -数论专题-扩展欧几里德

POJ 1061 青蛙的约会 Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%lld & %llu Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰

POJ 1061 (扩展欧几里德算法)

题意:两只青蛙在同一个纬度上跳跃,给定每个青蛙的开始坐标和每秒跳几个单位,纬度长为L,求它们相遇的最短时间. 析:开始,一看只有一组数据,就想模拟一下,觉得应该不会超时,但是不幸的是TLE了,我知道这肯定是一个数学题,不过刚开始没想到是扩展欧几里德,后来才发现这个可以转化为这个算法. 我们假设刚开始它们的坐标分别是x,y,它们的速度分别是m,n,坐标轴长为L,那么经过t次跳跃后它们的距离之差就是L(想一想是不是,可以画图看看). 所以(mt-x) - (nt-y) = kL;可转化为kL + (

POJ 2891 扩展欧几里德

这个题乍一看跟剩余定理似的,但是它不满足两两互素的条件,所以不能用剩余定理,也是给了一组同余方程,找出一个X满足这些方程,如果找不到的话就输出-1 因为它不满足互素的条件,所以两个两个的合并,最后合成一个. 题目给定的是 M % m1 = r1 M % m2 = r2 ...... M % mn = rn 只需将两个式子合并成一个式子,那么这个合并的这个式子就可以继续和下面的式子继续合并,知道合到最后一个式子. 首先来看下两个式子怎么合并. M % m1 = r1    可以写成  M = k1

POJ 1061 青蛙的约会 (扩展欧几里德)

两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的.但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的.为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面. 我们把这两只青蛙分别叫做青蛙A和

POJ 2891-Strange Way to Express Integers(扩展欧几里德)

题目地址:POJ 2891 题意:给你k组同余关系,每组包含一个ai和ri,让你找出一个最小的数m,满足m%a1=r1,m%a2=r2.......m%ak=rk. 思路:纵观上述公式,很熟悉,其实就是求两两公式之间的最小值,例如K=3,那么先求第一组和第二组的最小,然后合并第一组和第二组,然后用合并之后的再和第三组找最小,最后的结果就是最终的结果.也就是这个题分两部分来完成. 1.找出两组最小.对于m%a1=r1和m%a2=r2可以得出两个公式m=a1*x+r1,m=a2*y+r2(x,y相当

POJ - 1061 青蛙的约会 (扩展欧几里得算法)

Description 两只青蛙在网上相识了,它们聊得很开心,于是觉得很有必要见一面.它们很高兴地发现它们住在同一条纬度线上,于是它们约定各自朝西跳,直到碰面为止.可是它们出发之前忘记了一件很重要的事情,既没有问清楚对方的特征,也没有约定见面的具体位置.不过青蛙们都是很乐观的,它们觉得只要一直朝着某个方向跳下去,总能碰到对方的.但是除非这两只青蛙在同一时间跳到同一点上,不然是永远都不可能碰面的.为了帮助这两只乐观的青蛙,你被要求写一个程序来判断这两只青蛙是否能够碰面,会在什么时候碰面. 我们把这