博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【lydsy1407】拓展欧几里得求解不定方程+同余方程
阅读量:4630 次
发布时间:2019-06-09

本文共 3037 字,大约阅读时间需要 10 分钟。

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1407

 

题意:

有n个野人,野人各自住在第c[i]个山洞中(山洞成环状),每年向前走p[i]个山洞,到这个山洞住下来。

每个野人的寿命为l[i],问至少需要多少个山洞,才能让野人在有生之年永远不住在同一个山洞。

 

题解:

原本不会拓展欧几里得和同余方程,在这里尽量详细地写一下由这题学到的东西。

我原本是从网上看各类题解然后打的,因为不理解和某些题解上的错误,导致调了很久。

下面写我的题解,如有错误,敬请指出。

 

设山洞的数量为m。

首先,对于n=2时,若相遇,则得同余方程 c[i]+x*p[i] = c[j]+x*p[j] (mod m)

移项,得:(p[i]-p[j])*x=c[j]-c[i] (mod m)

即:(p[i]-p[j])*x + m*y = c[j]-c[i]

则由于p[i]-p[j]、m、c[j]-c[i]已知,该方程相当于 a*x+b*y=c,可用拓展欧几里得求解。

若该方程无解,或x小于l[i]且x小于l[j](注意是并且的关系,因为一个死了一个活着也是不能相遇的),则不会相遇。

 

所以,由于n<=15,可以从max(c[i])开始枚举m(因为开始时野人都不在同一个山洞,max(c[i])一定大于等于n),两两匹配,若都不能相遇,则当前的m值为最小整数解。

 

相关: 用拓展欧几里德算法求不定方程 a*x + b*y = c:

推荐一篇很好的博文:http://www.cnblogs.com/Rinyo/archive/2012/11/25/2787419.html

如果c不是gcd(a,b)的倍数,则该方程无解。

证明:

设g=gcd(a,b),则a=a'g,b=b'g

ax+by=c可化为g(a'x+b'y)=c

由于g、(a'x+b'y)、c都是整数,所以c必然是g的倍数。

 

拓展欧几里得:

int exgcd(int a,int b){    if (b == 0) { x=1,y=0; return a; }    int t = exgcd (b,a%b,x,y);    int x0 = x , y0 = y;    x = y0; y = x0-(a/b)*y0;    return t;}

 

证明:

ax + by = gcd(a,b)

bx'+(a%b)y'=gcd(b,a%b)

因为gcd(a,b) = gcd(b,a%b)

所以ax+by = bx'+(a%b)y'

代入a%b =  a - ⌊a/b⌋*b (⌊⌋是向下取整符号)

ax + by = bx' + (a - ⌊a/b⌋*b)y'

ax + by = ay' + b(x'-⌊a/b⌋y')

所以: x = y'  y = x'-⌊a/b⌋*y'

回溯即可得出答案。

 

此处求出的x和y是一组可行解,可以利用通式 

x = x' + k*b

y = y'  - k*a

求出最小整数解。

 

注意:ax + by = c 求的是c是gcd(a,b)的倍数时的解。

方法一:

          方程两边同时除以g

          a'=a/g   b'=b/g   c'=c/g

          得a'x+b'y=c' 

          用拓展欧几里德算法求解a'x'+b'y'=1

          则 x = x'*c'  y = y'*c'

          这时,在用通式求最小整数解时加减的应是b'

方法二:

          我们可以直接求出ax’ + by’ =gcd(a,b)

          则 x = x'*c/g   y = y' * c/g

          这时应注意,在求通式求最小整数解加减的仍应是b/g。(注意!)

 

代码如下:

1 #include
2 #include
3 #include
4 #include
5 using namespace std; 6 7 const int N=20,M=1000010; 8 int n; 9 int cc[N],p[N],l[N];10 11 int maxx(int x,int y) {
return x>y ? x:y;}12 int minn(int x,int y) {
return x
0 ? x:-x;}14 15 int gcd(int a,int b)16 {17 if(b==0) return a;18 return gcd(b,a%b);19 }20 21 void exgcd(int a,int b,int &x,int &y)22 {23 if(b==0) {x=1,y=0;return ;}24 exgcd(b,a%b,x,y);25 int x0=x,y0=y;26 x=y0;y=x0-(a/b)*y0;27 return ;28 }29 30 bool check(int m)31 {32 for(int i=1;i<=n-1;i++)33 for(int j=i+1;j<=n;j++)34 {35 int a=p[i]-p[j];36 int b=m;37 int c=cc[j]-cc[i];38 39 int g=gcd(a,b);40 if(c%g) continue;41 a/=g;b/=g;c/=g;//b在此处可能变为负42 int x,y;43 exgcd(a,b,x,y);44 x=x*c;y=y*c;45 while(x>0) x-=myabs(b);46 while(x<=0) x+=myabs(b);47 if(x<=minn(l[i],l[j])) return 0;//48 }49 return 1;50 }51 52 int main()53 {54 scanf("%d",&n);55 int mx=n;56 for(int i=1;i<=n;i++)57 {58 scanf("%d%d%d",&cc[i],&p[i],&l[i]); 59 mx=maxx(mx,cc[i]); 60 }61 for(int i=mx;i<=M;i++)62 {63 if(check(i)) {printf("%d\n",i);break;}64 }65 return 0;66 }
View Code

 

转载于:https://www.cnblogs.com/KonjakJuruo/p/4763923.html

你可能感兴趣的文章
ae工具是一种特殊的命令
查看>>
名人名言
查看>>
异常处理:写一个方法void triangle(inta,intb,int c),判断三个参数是否能构成一个三角形。...
查看>>
自组织神经网络介绍:自组织特征映射SOM(Self-organizing feature Map),第三部分
查看>>
如何自己编译生成hadoop的eclipse插件,如hadoop-eclipse-plugin-2.6.0.jar
查看>>
Markdown打造高逼格博客
查看>>
前端模块化(五):RequireJs
查看>>
SQLiteOpenHelper
查看>>
arcgis js api 4.x 基于tomcate的离线开发环境搭建
查看>>
js中的函数对象
查看>>
前后台交互实例二:前台通过django在数据库里面增删改查数据
查看>>
全部选择和全部取消多选框
查看>>
Haproxy+Keepalived负载均衡
查看>>
Github问题An error occurred trying to download
查看>>
在windows下使用TortoiseGit提交代码到github
查看>>
SpringMVC常用配置-处理程序异常以及404错误
查看>>
codesmith连接mysql
查看>>
对于配置web.config的问题
查看>>
spark定制之六:sql版start.scala
查看>>
JavaScript-2.内置对象---简单脚本之弹出对话框显示当前时间 ---ShinePans
查看>>