扩展欧几里德

P1009清帝之惑之康熙

背景

康熙是中国历史乃至世界历史中最伟大的帝王之一,清除螯拜,撤除三藩,统一台湾,平定准葛尔叛乱;与此同时,出众的他也被世界各国遣清使臣所折服。康熙是历史上少有的全人,不仅文武兼得,而且在各各方面都有见地,比如说航海、数学、英语、构图、建筑等等。一个最好的例子可以证明:康熙当年演算代数题的草稿纸至今仍然保存完好。

话说康熙掌权之后,每天都抽空做数学题,特别是无聊题。这些天,某某老师开始教他做一些奇怪的题目。在第一节课的时候,老师就问了康熙一个超BT的题目:

描述

话说西汉时期,汉武帝刘彻派遣张骞出使西域,欲同月氏国结交而共驱匈奴。同时,月氏国也欲同大汉结交,也派出使者康破伦出使大汉,可是因为月氏国对于大汉的认知甚少,康破伦同样向西出使大汉。一开始,张骞从大汉出发,康破伦从月氏国出发,两人都在同一纬度线上,张骞所处的经度为x,康破伦所处的经度为y;接下来,两人同时向西走,而且只能向西走,张骞每天走m公里,康破伦每天走n公里,且每天走路的速度不变,也不停下来休息;这样两人就在这一条长为L的纬度线上一直向西走。问:过了多少天之后张骞和康破伦会碰面,并磋商两国结交之事(所谓碰面,是指两人处在同一经度上)。

这下,康熙犯难了,他还是个不大的青年,怎么可能做得出这么难的题目;但是,他又是统领全国的帝皇,怎么能在老师面前丢这么大一个面子。康熙想:不行!一定得把这个题做出来!(然后就有了下面这段记录)
第一天,……
第二天,…………
第三天,………………
第四天,……………………
第五天,…………………………
第六天,………………………………
第七天,……………………………………!!!!!!!
啊!第七天,康熙终于打了7个感叹号,得出了一个重要的结论!!!!!那就是——做不出来。(汗),没办法,他只有请教你,他的挚友,帮他解决这一难题。康熙答应你,如果你把这一题做出来了,你将得到御赐赏银一万万mod1两!为了改变你生活的现状——衣衫褴褛、闻鼠起舞、蟑螂为伴,你下定了决心——我一定得把这题解决!

格式

输入格式

输入只包括一行5个整数x,y,m,n,L
其中0<x≠y < =2000000000,0 < m、n < =2000000000,0 < L < =2100000000。

输出格式

输出碰面所需要的天数,如果永远不可能碰面则输出一行"Impossible"。

样例1

样例输入1[复制]

1 2 3 4 5

样例输出1[复制]

4

限制

各个测试点2s

表达式: ax+by=n

ax+by=gcd(a,b)  一定有解, ax+by=n是这组解的n/gcd(a,b)倍;
若ax+by=n有解,则 n/gcd(a,b)是整数。
ax+by=gcd(a,b)的求解过程如下:
辗转相除法
a           b              gcd(a,b)
2           3                   1
3           2                   1
2           1                   1             
1           0      在这求得gcd(a,b)=1,  x=1, y= 0
回带
x             y   (回带时x=y,y=x-(a/b)*y) 由ax+by=bx+a%by 解得
0 1
1 -1
-1 1
所有得到  ax+by=gcd(a,b)  的 一组解 x0     y0
所以  ax+by=n 的一组解为  
x1=x0*n/gcd(a,b)         
y1=y0*n/gcd(a,b)
求通解:
                                                                 ax+by=n
                                                            ax1+by1=n
              ax1+ab/gcd(a,b)*k+by1-ab/gcd(a,b)*k=n                        (k为整数)
               a( x1-b/gcd(a,b)*k )+b( y1-a/gcd(a,b)*k )=n
得:
x=x1-b/gcd(a,b)*k
y=y1-a/gcd(a,b)*k
AC代码:
#include<iostream>//c++
#include<cmath>//数学公式
#include<cstdlib>//malloc
#include<cstring>
#include<string>
#include<cstdio>//输入输出
#include<algorithm>//快排
#include<queue>//队列
#include<functional>//优先队列
#include<stack>//栈
#include<vector>//容器
#include<map>//地图  if continue
typedef long long ll;
const int N=501;
using namespace std;
long long gcd(ll a,ll b,ll &x,ll &y)
{
    if(b==0){
        x = 1;
        y = 0;
        return a;
    }
    ll g = gcd(b, a%b, x, y);
    ll tmp = x;
    x=y;
    y=tmp-(a/b)*y;
    return g;
}
int main()
{
    ll a,b,c,n,m,l,x,y;
    while(cin>>x>>y>>m>>n>>l)
    {
        a=(l+m-n)%l;
        b=l;
        n=(y-x+l)%l;//ax+by=n  
        c=gcd(a,b,x,y);//a'x+b'y=n'         x1
        if(n%c) {cout<<"Impossible"<<endl;return 0;}
        n/=c;b/=c;//n' b'
        x*=n;     //x0=n'x1
        x%=b;
        if(x<0) x+=b;
        cout<<x<<endl;
    }
	return 0;
}

http://oj.acm.zstu.edu.cn/JudgeOnline/problem.php?id=4269

#include<bits/stdc++.h>
using namespace std;
const int N=20000+10;
const int inf=0x3f3f3f3f;
typedef long long ll;
ll gcd(ll x,ll y)
{
    return y?gcd(y,x%y):x;
}
int main()
{
    ll n,k,a,b,c,x,y;
    while(~scanf("%lld%lld%lld%lld%lld",&n,&k,&a,&b,&c))
    {

        if(a<b) swap(a,b);
        if(a<c) swap(a,c);
        if(b<c) swap(b,c);//保证 a、b为自然数
        if(a*k<n || c*k>n)//k>=x+y  n>=0
        {
            printf("No\n");
            continue;
        }
        a=a-c;
        b=b-c;
        n=n-c*k;
		//对于不完全为 0 的整数 a,b那么一定存在整数 x,y 使得 gcd(a,b)=ax+by。
		if(a==b&&b==0)	puts(n?"No":"Yes");//事实上 这个时候的n 一定为0
		else puts(n%gcd(a,b)?"No":"Yes");
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值