1. 程式人生 > >ACM:數論專題(6)——模線性方程組

ACM:數論專題(6)——模線性方程組

題目描述:
給定n組除數Mi和餘數Ri (1≤i≤n, Ri<Mi), 定義方程組如下:
        x % M1 = R1
        x % M2 = R2
        x % M3 = R3
            ...
        x % Mn = Rn

求解滿足以上方程組的x的最小正整數解。

解答:
    題目中定義的方程組稱為“模線性方程組”,我們可以採用一種迭代的方式進行求解。

·基本情況:
    首先考慮方程組中只包含2個方程的情況:
        x % M1 = R1..................................................(F1)
        x % M2 = R2..................................................(F2)

假設: x = k1 * M1 + R1, x = k2 * M2 + R2,此時:
        k1 * M1 + R1 = k2 * M2 + R2
    =>  k1 * M1 - k2 * M2 = R2 - R1..................................(T)

M1, M2, R1, R2 都是已知的常數,這樣就得到了一個以k1, k2為未知數的二元一次方程。此時,只要找到(T)式的一組整數解,然後代入,就可以找到滿足由方程(F1) 和 (F2)的一個x解。
    
    求解(iii)式的過程可以利用拓展歐幾里得演算法 簡要說明其步驟如下:
   記:A = M1, B = M2, C = R2 - R1, x = k1, y = k2那麼方程(iii)就可以抽象為:
             Ax + By = C..........................................(E1)
根據拓展歐幾里得定理,
方程E1有整數解(x 和 y均為整數)的充要條件是:C可以被A和B的最大公約數整除,即:C % gcd(A, B)。利用這個條件就可以判定方程是否有整數解。
    如果通過以上判定方式判定方程有整數解,則可以利用下面的方法,找出方程的一組解:
    記:方程E2: 
            Bx + (A%B)y = gcd(B, A%B)..............................(E2)
由輾轉相除法可知:gcd(A, B) = gcd(B, A%B), 因此:方程E1和E2的等號右邊項是相同的,因此:
            Ax + By = Bx + (A%B)y = Bx + [A - (A/B)*B]y = Bx + Ay - B*(A/B)y
         => Ax + By = Ay + B * [x - (A/B)y]

此時,如果已經找到方程E2的一組解(x2, y2), 代入上式可得:
            Ax + By = Ay2 + B * [x2 - (A/B)y2]
因此,x = y2, y = x2 - (A/B)y2 就是方程E1的一組解。
    根據以上特性,給出方程E1後,我們可以將其轉化為方程E2, 然後求解E2後,得到E1的解。至於方程E2的求解,則可以遞迴地進行,令:E2中:A = B, B = A%B, 將其轉化為E3,再通過求解E3, 得到E2,如此迴圈往復,直到某一輪迭代的方程Ei中,引數A以被引數B整除,即:A%B = 0, 那麼此時,gcd(A, B) = B, 方程就化為:Ax + By = B. 顯然,這個方程有一組解為:x = 0, y = 1, 然後再依次回溯至方程:Ei-1, Ei-2 ... E1, 就可以求解出原方程的一組解。

    求解完成後,將解得的k1的值代入:k1*M1 + R1, 就能得到一個滿足方程(F1)和(F2)的一個x值。
    以上方法只能保證可以找到滿足方程組的某一個解,但卻不能保證題目中要求的最小正整數解。為了得到最小正整數解,還需要以下的處理:假設已經找到了方程E1的一組解:x1, y1, 並記此時計算得到的滿足方程(F1)和(F2)的x值為x0。將x1,y1代入方程E1得:
        Ax1 + By1 = gcd(A, B) 
    =  Ax1 + By1 + sAB - sAB 
    =  A(x1-sB) + B(y1+sA) = A(x1+sB) + B(y1-sA)

其中s為任意整數。
    以上式子表明:如果x1, y1是原方程的解,那麼x1±sB, y1±sA 也是原方程的解。對應於:
A = M1, B = M2, C = R2 - R1, x = k1, y = k2, 我們可以得到一組x值:
        x = k1 * M1 + R1 = (x1±B)*M1 + R1 = x1*M1 + R1 ± BM1 = x0±s*M2*M1 
因此通過調整上式中的s的值,就一定可以找到滿足原方程組的最小正整數解。

·拓展:
    上文中提供了一種求解僅包含2個方程的模線性方程組的解的方法。而對於包含多個方程的方程組,則可以採用迭代的策略進行求解,方法如下:
    假設原方程組中包含n個方程,分別記作:F1, F2, ... Fn
    聯立方程F1和F2, 根據上文中的方法,F1和F2組成的方程組求得的解:
            x = x0 + s*M2*M1
此時,上式可以轉換為:
            x % (M2*M1) = x0 .................................(G2)
    記上面的方程為G2, 顯然,滿足方程G2的x值一定滿足方程F1和方程F2。此時聯立G2和F3,求解方程組後,得到的解就一定同時滿足方程:F1, F2, F3。此時,利用類似的方法,可以將G2和F3組成的方程組的解轉換為方程G3,然後聯立G3和F4求解方程組......以此類推。
    記方程F1為G1,我們可以發現:
        求解方程組G1和F2,得到的解滿足F1和F2,同時得到方程G2;
        求解方程組G2和F3,得到的解滿足F1, F2, F3, 同時得到方程G3;
        求解方程組G3和F4,
得到的解滿足F1, F2, F3, F4, 同時得到方程G4;
            .....
        
求解方程組Gn-2和Fn-1,得到的解滿足F1, F2, F3, ... , Fn-1, 同時得到方程Gn-1
求解方程組Gn-1和Fn,得到的解滿足F1, F2, F3, ... , Fn,此時不需要得到方程Gn, 因為得到的解滿足原方程組中的所有方程,求解完畢。輸入輸出格式:
    輸入:第1行為1個正整數N,表示方程組中的方程的個數;接下來的N行,每行2個數字,表示Mi和Ri
輸出:輸出一個整數,表示方程組的最小正整數解,如果方程組無解,則輸出-1。 
資料範圍:
     2 ≤ Mi ≤ 20,000,000
     0 ≤ Ri < Mi 

程式程式碼:

/****************************************************/
/* File        : Hiho_Week_97                       */
/* Author      : Zhang Yufei                        */
/* Date        : 2016-05-09                         */
/* Description : HihoCoder ACM program. (submit:g++)*/
/****************************************************/

#include<stdio.h>
#include<stdlib.h>

/*
 * Define the structure to record the result.
 * Parameters:
 *		@x & @y: The result (x, y).
 */
typedef struct node {
	long long x;
	long long y;
} result;

/*
 * This function computes the greatest common divisor of 2 numbers a and b.
 * Parameters:
 *		@a & @b: The 2 numbers to compute.
 * Returns:
 *		The greatest common divisor of a and b.
 */
long long gcd (long long a, long long b) {
	if(a % b == 0) {
		return b;
	} else {
		return gcd (b, a % b);
	}
}

/*
 * This function computes the lowest common multiple of 2 numbers a and b.
 * Parameters:
 *		@a & @b: The 2 numbers to compute.
 * Returns:
 *		The lowest common multiple of a and b.
 */
long long lcm (long long a, long long b) {
	long long g = gcd (a, b);
	return (a / g) * b;
}

/*
 * This function calculates the result of the equation:
 *	Ax + By = 1 using extend euclidean theory.
 * Parameters:
 * 		@A & @B: The parameter A, B in the equation.
 * Returns:
 * 		One result of this equation, if the equation don't have 
 *		a legal result, returns NULL.
 */ 
result* extend_euclidean (long long A, long long B) {
	result *r; 
	if(A % B == 0) {
		r = (result*) malloc (sizeof(result));
		r->x = 0;
		r->y = 1;
	} else {
		r = extend_euclidean (B, A % B);
		long long x = r->x;
		long long y = r->y;
		r->x = y;
		r->y = x - A / B * y;
	}
	return r;
}

/*
 * The main program.
 */
int main (void) {
	int N;
	scanf ("%d", &N);
	
	long long m1, r1, m2, r2;
	long long A, B, C;
	scanf ("%lld %lld", &m1, &r1);
	
	result *r;
	
	long long answer = 0;
	
	for(int i = 1; i < N; i++) {
		scanf ("%lld %lld", &m2, &r2);
		if(answer == -1) {
			continue;
		}
		A = m1;
		B = m2;
		C = r2 - r1;
		
		long long g = gcd (A, B);
		if(C % g != 0) {
			answer = -1;
			continue;
		}
		
		long long lc = lcm (A, B);
						
		A /= g;
		B /= g;
		C /= g;
		
		r = extend_euclidean (A, B);
		r->x *= C;
		r->x %= B;
		
		answer = m1 * r->x + r1;

		while(answer < 0) {
			answer += lc;
		}
		
		while(answer > lc) {
			answer -= lc;
		}
		
		m1 = lc;
		r1 = answer;
	} 
	
	printf("%lld\n", answer);
	
	return 0;
}


相關推薦

ACM數論專題(6)——線性方程組

題目描述: 給定n組除數Mi和餘數Ri (1≤i≤n, Ri<Mi), 定義方程組如下:        x % M1 = R1        x % M2 = R2         x % M3 = R3             ...         x % M

hihocoder 1303 : 數論六·線性方程組

hihocoder 1303 描述 小Ho:今天我聽到一個挺有意思的故事! 小Hi:什麼故事啊? 小Ho:說秦末,劉邦的將軍韓信帶領1500名士兵經歷了一場戰鬥,戰死四百餘人。韓信為了清點人數

POJ.2065.SETI(高斯消元 線性方程組)

oid 求解 一個 fine earth std htm unique line 題目鏈接 http://blog.csdn.net/Clove_unique/article/details/54381675 http://blog.csdn.net/u013081425/

HDU.3571.N-dimensional Sphere(高斯消元 線性方程組)

con 需要 etc oid 如果 git inline cpp 由於 題目鏈接 高斯消元詳解 /* $Description$ 在n維空間中給定n+1個點,求一個點使得這個點到所有點的距離都為R(R不給出)。點的任一坐標|xi|<=1e17. $Solution$

POJ 1061 青蛙的約會(拓展歐幾裏得算法求解線性方程組詳解)

scrip 坐標 出發點 開心 以及 NPU tdi 青蛙的約會 方程組 題目鏈接: BZOJ: https://www.lydsy.com/JudgeOnline/problem.php?id=1477 POJ: https://cn.vjudge.net/problem

如何使用拓展歐幾裏得算法求解線性方程組(詳解)

得出 bsp 次方 及其 根據 約數 www 求解 回退   式子a≡b(mod n)稱為a和b關於模n同余,它的充要條件是a-b是n的整數倍,即a-b=zn(其中z取整數)。 而模線性方程組ax≡b(mod n)可以寫成ax-b=zn(其中z取整數),移項可得 ax-zn

【模板】合併線性方程組(POJ2891)

Description   給定\(n\)組同餘關係,求解最小的非負整數\(x\),滿足\(x \mod a_i = r_i\) Input   第一行一個整數\(n\)   接下來\(n\)行,每行兩個整數,分別表示\(a_i\) 和 \(r_i\) Output   一個正整數\(x\)即最小正

線性方程組(poj2115)

#include<cstdio> #define ll long long ll d; ll x,y; void exgcd(ll a,ll b){ if(b==0){ d=a; x=1; y=0; return ; } exgcd(b,a%b); ll t=x;

hihoCoder 1303 線性方程組

模線性方程組 描述: 給定了n組除數m[i]和餘數r[i],通過這n組(m[i],r[i])求解一個x,使得x mod m[i] = r[i]。 演算法思想: 一開始就直接求解多個方程不是太容易,我們從n=2開始遞推: 已知: x mod m[1] = r[1] x

線性方程組(中國剩餘定理)

《孫子算經》裡有這樣一個問題,“今有物不知其數,三三數之剩二(除以3餘2),五五數之剩三(除以5餘3),七七數之剩二(除以7餘2),問物幾何?”,解決這個問題的方法稱為中國剩餘定理,也叫孫子定理。中國古代還有一個叫做“韓信點兵”的問題,和這個問題本質是一樣的。 很明顯這個物

線性方程組、中國剩餘定理

對模線性方程 ax = b (mod m),有 ax = k*m + b,其中 k 是整數。 移項後有 ax - km = b,轉化到了 EXGCD 的解法。 若有模線性方程組如下: x=b1(modm1)x=b1(modm1) x=b2(modm2

poj 2891 (一般線性方程組)

#include <stdio.h> typedef long long LL; const int maxn = 1e5+10; const int inf = 0x3f3f3f3f;

HDU 1573 X問題 (中國剩餘定理 線性方程組

思路: 方法1: 問題可以轉化為求模線性方程組。 設要求得的滿足方程組的最小正整數為n; n=b1(moda1) n=b2(moda2) 可以得到: n=b1+x∗a1=b2+y∗a

演算法總結之求解線性方程組

1)求解模線性方程 ax = b(mod n)   方程ax = b(mod n) -> ax = b + ny ->ax - ny = b   -> ax + n (-y) =

poj 2891 Strange Way to Express Integers (解線性方程組)

題意:有一個數x,給定k組ai和ri,使得x%ai=ri       求x最小為多少 分析:求解模線性方程組   x = a1(mod m1)   x = a2(mod m2)   x = a3

線性方程組-非互質中國剩餘定理 HDU3579 HDU1573

問題描述:給出bi,ni的值,且n1, n2, n3,…, ni兩兩之間不一定互質,求Res的值? 解:採用的是合併方程的做法。  這裡將以合併第一第二個方程為例進行說明  由上圖前2個方程得(設k1、k2為某一整數): #include <iostream>

Android Things 專題6 完整的栗子運用TensorFlow解析圖像

out 好玩的 mod tex 解答 debug 碼流 寫文件 應用 文| 谷歌開發技術專家 (GDE) 王玉成 (York Wang) 前面絮叨了這麽多,好像還沒

數值分析(三)C++實現線性方程組的高斯-賽德爾迭代法

線性方程組的直接解法之後,就輪到迭代解法了,直接解法針對的是低階稠密矩陣,資料量較少,而工程上有更多的是高階係數矩陣,使用迭代法效率更高,佔用的空間較小。 迭代法的最基本思想就是由初始條件,比如說初始解向量隨便列舉一個,就0向量也行,然後進行迭代,k到k+1,一步一步從k=1開始去逼近真實解

數值分析--線性方程組解的演算法(6種)(附演算法百度雲連結,純手寫原創)

先上乾貨百度雲(純手寫,純HTML,可直接開啟),如下: 注:參考書籍《數值分析》北京航空航天大學出版社 一、順序GUASS消去法 點進去如下,先輸入要解的N階矩陣: 比如,我們輸入3: 出現下方的矩陣框,為(N+1)*N的增廣矩陣,輸入待計算的矩陣,然

ACM搜尋演算法專題(1)——24點

題目描述:給定4個數字,判定這4個數字是否可以通過運算得到結果24。運算操作包括:加、減、乘、除,允許變換數字的順序,允許使用括號改變運算順序。     即:判定是否存在一種通過在下面的圓圈中新增運算子以及新增括號的方式使得等式成立:             a ○ b ○