POJ1061:青蛙的约会+POJ2115C Looooops+UVA10673Play with Floor and Ceil(扩展欧几里得)

http://poj.org/problem?id=1061

第一遍的写法:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
long long x,y,m,n,l,j1,j2;
long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}
void extend(long long a,long long b,long long &x1,long long &y1)
{
    if(b==0)
    {
        x1=1;
        y1=0;
        return ;
    }
    extend(b,a%b,x1,y1);
    long long t=x1;
    x1=y1;
    y1=t-a/b*y1;
    return ;
}
int main()
{
    while(scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l)!=EOF)
    {
        long long a=n-m;
        long long b=l;
        long long c=x-y;
        long long temp=gcd(a,b);
        if(c%temp!=0||n==m)
        {
            printf("Impossible\n");
            continue;
        }
        a/=temp;
        b/=temp;
        c/=temp;
        extend(a,b,j1,j2);
        long long t=-(j1*c)/b;
        j1=c*j1+t*b;
        if(j1<0)
        {
            if(b>0) j1+=b;
        }
        printf("%lld\n",j1);
    }
    return 0;
}
View Code

第二遍:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
long long x,y,m,n,l,j1,j2;
long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}
void extend(long long a,long long b,long long &x1,long long &y1)
{
    if(b==0)
    {
        x1=1;
        y1=0;
        return ;
    }
    extend(b,a%b,x1,y1);
    long long t=x1;
    x1=y1;
    y1=t-a/b*y1;
    return ;
}
int main()
{
    while(scanf("%lld%lld%lld%lld%lld",&x,&y,&m,&n,&l)!=EOF)
    {
        long long a=n-m;
        long long b=l;
        long long c=x-y;
        long long temp=gcd(a,b);
        if(c%temp!=0||n==m)
        {
            printf("Impossible\n");
            continue;
        }
        a/=temp;
        b/=temp;
        c/=temp;
        extend(a,b,j1,j2);
        long long t=((j1*c)%b+b)%b;
        printf("%lld\n",t);
    }
    return 0;
}

POJ2115:

题意:

对于C的for(i=A ; i!=B ;i +=C)循环语句,问在k位存储系统中循环几次才会结束。

若在有限次内结束,则输出循环次数。

否则输出死循环。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
long long a,b,c,k;
long long x1,x2;
long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}
void extend(long long A,long long B,long long &x1,long long &y1)
{
    if(B==0)
    {
        x1=1;
        y1=0;
        return ;
    }
    extend(B,A%B,x1,y1);
    long long t=x1;
    x1=y1;
    y1=t-(A/B)*y1;
}
int main()
{
    while(scanf("%lld%lld%lld%lld",&a,&b,&c,&k)!=EOF)
    {
        if(a==0&&b==0&&c==0&&k==0) break;
        long long A=c;
        long long B=pow(2,k);
        long long C=b-a;
        long long temp=gcd(A,B);
        if(C%temp)
        {
            printf("FOREVER\n");
            continue;
        }
        A/=temp;
        B/=temp;
        C/=temp;
        extend(A,B,x1,x2);
        long long t=(C*x1%B+B)%B;
        printf("%lld\n",t);
    }
    return  0;
}

题目解析:
  这两道题目都是简单的扩展欧几里得求二元一次方程最优解,理解了就好做了,浪费了一天多的时间才搞透,脑残的孩子果断得慢慢学。

 

更通常的是:我们需要求解方程的最小整数解 若我们已经求得x0,y0为方程中x的一组特解,那么 x=x0+b/gcd(a,b)*t,y=y0-a/gcd(a,b)*t(t为任意整数)也为方程的解 且b/gcd(a,b),a/gcd(a,b)分别为x,y的解的最小间距,所以x在0~b/gcd(a,b)区间有且仅有一个解, 同理y在0~a/gcd(a,b)同样有且仅有一个解,这个解即为我们所需求的最小正整数解。

为什么b/gcd(a,b),a/gcd(a,b)分别为x,y的解的最小间距? 解:假设c为x的解的最小间距,此时d为y的解的间距,所以x=x0+c*t,y=y0-d*t(x0,y0为一组特解,t为任意整数)  带入方程得:a*x0+a*c*t+b*y0-b*d*t=n,因为a*x0+b*y0=n,所以a*c*t-b*d*t=0,t不等于0时,a*c=b*d 因为a,b,c,d都为正整数,所以用最小的c,d,使得等式成立,ac,bd就应该等于a,b的最小公倍数a*b/gcd(a,b), 所以c=b/gcd(a,b),d就等于a/gcd(a,b)。

所以,若最后所求解要求x为最小整数,那么x=(x0%(b/gcd(a,b))+b/gcd(a,b))%(b/gcd(a,b))即为x的最小整数解。 x0%(b/gcd(a,b))使解落到区间-b/gcd(a,b)~b/gcd(a,b),再加上b/gcd(a,b)使解在区间0~2*b/gcd(a,b), 再模上b/gcd(a,b),则得到最小整数解(注意b/gcd(a,b)为解的最小距离,重要)

UVA10673Play with Floor and Ceil

题目解析:

超级大水题,模版题。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;
long long p,q,x,k;
long long x1,x2;
long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}
void extend(long long a,long long b,long long &x1,long long &y1)
{
    if(b==0)
    {
        x1=1;
        y1=0;
        return ;
    }
    extend(b,a%b,x1,y1);
    long long t=x1;
    x1=y1;
    y1=t-a/b*y1;
    return ;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%lld%lld",&x,&k);
        long long a=floor((double)x/(double)k);
        long long b=ceil((double)x/(double)k);
        long long c=x;
        long long temp=gcd(a,b);
        a/=temp;
        b/=temp;
        c/=temp;
        extend(a,b,x1,x2);
        x1=x1*c;
        x2*=c;
        printf("%lld %lld\n",x1,x2);
    }
    return 0;
}
View Code

 

posted @ 2015-01-18 17:07  人艰不拆_zmc  阅读(296)  评论(0编辑  收藏  举报