求解丢番图方程
丢番图方程
形如ax+by=c,其中a,b,c为整数的方程,现在要求x,y的整数解。
如2x+3y=5
显然这个方程有整数解(x=1,y=1)同时有无穷多个解。
如2x+4y=5
显然这个方程没有整数解。
下面的定理告诉我们这种方程有解的条件及所有解的形式。
定理1:设a,b是整数且d=(a,b)。如果c不能被d整除那么方程ax+by=c没有整数解。如果c能被d整除那么存在无穷多个整数解,另外,如果x=x0,y=y0是方程的一个特解,那么所有的解可以表示为:
X=x0+(b/d)*n
Y=y0-(a/d)*n
其中n是整数
定理2:如果a1,a2,…,an是正整数,那么方程a1x1+a2x2+…+anxn=c有整数解当且仅当d=(a1,a2,……,an)能整除c,另外当存在一个解的时候,那么方程有无穷多个解解n元一次不定方程a1x1+a2x2+…+anxn=c(a1,a2,…,an∈N)时,可先顺次求出(a1,a2)=d2,(d2,a3)=d3,……,(d(n-1),an)=dn.若c能被dn整除,则方程有解,作方程:
A1x1+a2x2=d2t2
D2t2+a3x3=d3t3
……
D(n-1)t(n-1)+anxn=c
求出最后一个方程的所有解,然后把tn-1的每一个值代入倒数第二个方程,求出它的所有解,依次类推,即可得所有解。
不定方程组的解
M个n元一次不定方程组成的方程组,其中m<n,可以消去m-1个未知数,从而消去m-1个不定方程,将方程组转化为1个n-m+1元的一次不定方程。
欧几里德算法
即辗转相除法,计算整数A, B最大公约数。
基本算法:设 a = kb + r,其中a,b,k,r都是整数,则 gcd(a,b) = gcd(b,r),即 gcd(a,b) = gcd(b,a%b) 。
证明: a = kb + r; 则r = a%b ; 设m为 a , b 的一个公约数,则 m|a , m|b,而 r = a - kb; 所以 m|r (注:m整除r,r能被m整除),因此m也是 (b , a%b) 的公约数;
设m为 b , r 的一个公约数,则 m|b , m|r,而 a = r + kb; 所以 m|a ,因此m也是 (a , b) 的公约数;因此 (b , a%b) 与 (a , b) 公约数相同,最大公约数也一定相同,得证。
欧几里德算法
代码现实
int gcd(int a,int b) { if(b==0) return a; return gcd(b, a%b); }
扩展欧几里德算法
基本算法:对于不完全为 0 的非负整数 a,b,必然存在整数对 x,y ,使得 ax + by = gcd(a,b) 。
证明: 前文得证 gcd(a,b) = gcd(b,a%b) ; 所以 ax + by = bx1 + %by1 ;
化简得 ax + by = ay1 + b(x1 - (a/b)*y1) ;
得到:x = y1 ; y = (x1 - (a/b)*y1) ;
递归的最终停止结果为 a = gcd( a , b) , b = 0 , 此时 x = 1 , y = 0 ;
扩展欧几里德算法
int exgcd(int a,int b,int &x,int &y) { if(b == 0) { x = 1; y = 0; return a; } int r = exgcd(b,a%b,x,y); int temp = x; x = y; y = temp-a/b*y; return r; }
扩展欧几里德算法求解丢番图方程
用扩展欧几里德算法求解丢番图方程ax+by=c ,系数 a, b, c 为任意整数。丢番图方程有解的充要条件为c%gcd(a,b)==0 。
由前一章节可知 ax + by = gcd(a,b) 存在整数解, 因此 c % gcd(a,b)==0 为丢番图方程有解的充分条件
代码实现的话与扩展欧几里德算法基本相同, 不同的地方就是最后的结果 x和y 要乘上倍数 c/gcd ( a, b) 。
密码
问题描述
有一个密码箱,0到n-1中的某此整数是它的密码,且满足;如果a和b都是它的密码,那么(a+b)%n也是它的密码(a,b可以相等,%表示整除取余数,下同),某人试了k次字码,前k-1次失败,最后一次成功了。
问:该密码箱最多有多少不同的密码。
输入格式
第一行两下整数分别表示n,k。
第二行为k个用空格分隔开的非负整数,表示每次试的密码。数据保证存在合法解。
输出格式
输出一行一个数,表示结果。
密码
样例输入
42 5
28 31 10 24
样例输出
14
数据规模
10% N≤104,k≤100
10% N≤109,k≤100
10% N≤109,k=1
60% k≤1000
100% 1≤k≤2500000,k≤n≤1014