bzoj 1477: 青蛙的约会
1477: 青蛙的约会
2017-08-27
Description
Input
Output
Sample Input
Sample Output
数论是个玄学的东西,还有那个叫欧几里得的人
数论入门难度的题,what?青蛙还约会?不会在之前被冻上?
总之,就是给你一个方程让你节一个令k最小的且k∈N*的解
不妨设跳的次数为k,总共跳了p圈;
那么就有(x+k*m)-(y+k*m)=p*L
变形一下就是(x-y)+k*(m-n)=p*L
移项得到k*(m-n)-p*L=-(x-y)->k*(n-m)+p*L=x-y
令A=m-n,B=L,C=x-y;则有k*A+B*p=C求解方程的最小k
这就用到EXgcd构造出一个满足题意的k,当C%gcd(A,B)!=0时,方程无 整数解
EX_gcd
long long exgcd(long long a,long long b) { if(b==0){x=1;y=0;return a;} long long r=exgcd(b,a%b); long long t=x;x=y;y=t-(a/b)*y; return r; }
证明:
现在已知方程的一组解x0,y0;求满足条件的解x1,y1;
那这个方程a*x0+b*y0=gcd(a,b); ①
令a=b,b=a%b则有b*x1+(a%b)*y1=gcd(b,a%b); ②
其中gcd(a,b)=gcd(b,a%b)则联立① ②则有:
a*x0+b*y0=b*x1+(a%b)*y1 ③
a%b≡a-⌊a/b⌋*b ④// ⌊⌋向下取整
联立③ ④则有a*x0+b*y0=b*x1+(a-⌊a/b⌋*b)*y1 ⑤
拆开⑤就是 a*x0+b*y0=b*x1+a*y1-⌊a/b⌋*b*y1 ⑥
根据群论 两边字母系数相同的放在相同位置就是a*x0+b*y0=a*y1+b*(x1-⌊a/b⌋*y1) ⑦
然后得出y1=x0 ⑧
x1-⌊a/b⌋*y1=y0 变形就是x1=y0+⌊a/b⌋*y1 ⑨
⑧ ⑨就是可以的一个解
=wow=
by:s_a_b_e_r
orz先%楼上数学dalao
这年头连青蛙都约会了
……好了言归正传接着证
求不定方程ax+by=c的可行解
于是楼上的exgcd证出了对于ax+by=gcd(a,b)的一组可行解
接着我们要求ax+by=c的一组解
事实上只有当c%gcd(a,b)==0的时候有整数解
证明:
假设c%gcd(a,b)!=0
那么c=k*gcd(a,b)+f,0<f<gcd(a,b) ①
由a*x+b*y=gcd(a,b),两边同乘k得 a*x*k+b*y*k=gcd(a,b)*k ②
①②联立得a*x*k+b*y*k+f=c
假设a<=b,那么0<f<gcd(a,b)<=a<=b
那么不存在一个整数m使得f=a*m
也就不存在整数解a*x*k+b*y*k+a*m=c -> a*(x*k+m)+b*(y*k)=c
替换一下可得不存在整数解使a*x+b*y=c
显然不成立╮(╯▽╰)╭
于是得证OvO
那上面的问题就好解决了
已知ax+by=gcd(a,b)的一组可行解,求ax+by=c的一组解
直接暴力将x,y *c/gcd(a,b) 就解决了
by:wypx
现在回来继续证
现在我们有一个可行解x0,y0;那么如何保证求出的x1最小呢?poi?
现在有一个结论如果x0,y0是解;x0,y0∈Z;
a*x+b*y=c;现在为了简单令k=gcd(a,b);
x=x0+b/k*T
y=y0-a/k*T(T∈Z)也是可行解;根据这个定理就可以找到最小的x满足题意;
证明:
设原方程a*x0+b*y0=c ①
那么我们可以在x0,y0的位置进行一个替换,即变形成:
a*(x1+b/k*T)+b*(y1-a/k*T)=c ②
把②打开就是a*x1+b*y1=c ③
再次联立①&③就是a*x1+b*y1=a*x0+b*y0 ④
这个式子恒成立和参数T没有关系,所以原方程成立;
原方程最小的x就是x=x*(c/k)%(b/r);但这样的x可能为负数
所以结果还要加上(x+(b/r))%(b/r);
即在原x基础上(x*(c/k)%(b/r)+(b/r))%(b/r);
#include<iostream> #include<cstdio> #include<cstdlib> #define ll long long using namespace std; ll x,y,m,n,L; ll xx,yy; ll A,B,C,gcd; ll EXgcd(ll a,ll b,ll &x,ll &y){ if(b==0){x=1,y=0;return a;} ll g=EXgcd(b,a%b,x,y); ll cnt=x; x=y; y=cnt-a/b*y; return g; } int main(){ cin>>xx>>yy>>m>>n>>L; A=-n+m;B=L;C=-xx+yy; if(A<0){A=-A,C=-C;} ll gcd=EXgcd(A,L,x,y); if(C%gcd){printf("Impossible");return 0;} else x=(x*(C/gcd)%(L/gcd)+(L/gcd))%(L/gcd); cout<<x; return 0; }
by:s_a_b_e_r
qwq感觉整道题都是他证的
我貌似就证了一个显而易见的结论……
丢代码……
#include<iostream> #include<cstdio> using namespace std; long long x,y,m,n,l; long long exgcd(long long a,long long b) { if(b==0){x=1;y=0;return a;} long long r=exgcd(b,a%b); long long t=x;x=y;y=t-(a/b)*y; return r; } int main() { long long p,q; cin>>p>>q>>m>>n>>l; long long a=m-n,b=l,c=q-p; if(a<0)a=-a,c=-c; int r=exgcd(a,b); if(c%r)cout<<"Impossible"<<endl; else {cout<< ( (x*(c/r)) % (b/r) + (b/r) ) %(b/r);} system("pause"); return 0; }
s;这只青蛙跳的好远,1e9的青蛙,好玄学
w:这就是这两只青蛙约会的下场↓↓
s:膜拜上面数学dalao
w:%%%⑨