1. 程式人生 > >hihoCoder 1303 模線性方程組

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 mod m[2] = r[2]

根據這兩個式子,我們存在兩個整數k[1],k[2]:

x = m[1] * k[1] + r[1]
x = m[2] * k[2] + r[2]

由於兩個值相等,因此我們有:

	m[1] * k[1] + r[1] = m[2] * k[2] + r[2]
=>	m[1] * k[1] - m[2] * k[2] = r[2] - r[1]

由於m[1],m[2],r[1],r[2]都是常數,若令A=m[1],B=m[2],C=r[2]-r[1],x=k[1],y=k[2],則上式變為:Ax + By = C。

是不是覺得特別眼熟。

沒錯,這就是我們之前講過的擴充套件歐幾里德

我們可以先通過gcd(m[1], m[2])能否整除r[2]-r[1]來判定是否存在解。

假設存在解,則我們通過擴充套件歐幾里德求解出k[1],k[2]。

再把k[1]代入x = m[1] * k[1] + r[1],就可以求解出x。

同時我們將這個x作為特解,可以擴展出一個解系:

X = x + k*lcm(m[1], m[2]) k為整數

lcm(a,b)表示a和b的最小公倍數。其求解公式為lcm(a,b)=a*b/gcd(a,b)。

將其改變形式為:

X mod lcm(m[1], m[2]) = x。

令M = lcm(m[1], m[2]), R = x,則有新的模方程X mod M = R。

此時,可以發現我們將x mod m[1] = r[1],x mod m[2] = r[2]合併為了一個式子X mod lcm(m[1], m[2]) = x。滿足後者的X一定滿足前兩個式子。

每兩個式子都可以通過該方法化簡為一個式子。那麼我們只要重複進行這個操作,就可以將n個方程組化簡為一個方程,並且求出一個最後的解了。

將其寫做虛擬碼為:

M = m[1], R = r[1]
For i = 2 .. N 
	d = gcd(M, m[i])
	c = r[i] - R
	If (c mod d) Then	// 無解的情況
		Return -1
	End If
	(k1, k2) = extend_gcd(M / d, m[i] / d)	// 擴充套件歐幾里德計算k1,k2
	k1 = (c / d * k1) mod (m[i] / d)	// 擴充套件解系
	R = R + k1 * M		// 計算x = m[1] * k[1] + r[1]
	M = M / d * m[i] 	// 求解lcm(M, m[i])
	R %= M 			// 求解合併後的新R,同時讓R最小
End For		
If (R < 0) Then 
	R = R + M
End If
Return R

AC程式碼:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

typedef long long ll;
int n;
ll m[1005],r[1005];

ll gcd(ll a, ll b){
    if(b == 0)
        return a;
    return gcd(b,a%b);
}

ll extend_gcd(ll a, ll b, ll &x, ll &y){
    if(a==0 && b==0) return -1;// 無最大公約數
    if(b == 0){x = 1; y = 0; return a;}
    ll d = extend_gcd(b,a%b,y,x);
    y -= a/b*x;
    return d;
}

ll solve(){
    ll M = m[0],R = r[0];
    for(int i = 1; i < n; ++i){
        ll d = gcd(M,m[i]);
        ll c = r[i]-R;
        if(c % d)
            return -1;// 無解的情況
        ll k1,k2;
        extend_gcd(M/d,m[i]/d,k1,k2);// 擴充套件歐幾里德計算k1,k2
        k1 = (c/d*k1)%(m[i]/d);// 擴充套件解系
        R += k1*M;// 計算x = m[1] * k[1] + r[1]
        M = M/d*m[i];// 求解lcm(M, m[i])
        R %= M;// 求解合併後的新R,同時讓R最小
    }
    if(R < 0)
        R += M;
    return R;
}

int main(){
    while(~scanf("%d",&n)){
        for(int i = 0; i < n; ++i){
            scanf("%d%d",&m[i],&r[i]);
        }
        printf("%lld\n",solve());
    }
    return 0;
}


相關推薦

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

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\)即最小正

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

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

線性方程組(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;

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

《孫子算經》裡有這樣一個問題,“今有物不知其數,三三數之剩二(除以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>

中國剩餘定理求解同餘線性方程組數互素和非互素的情況)

中國剩餘定理      中國剩餘定理是中國古代求解一次同餘方程組的方法,是數論中的一個重要定理。      設m1,m2,m3,...,mk是兩兩互素的正整數,即gcd(mi,mj)=1,i!=j,i,j=1,2,3,...,k. 則同餘方程組: x = a1

3行代碼 多元線性方程組

ges -1 bsp img src 方程組 線性方程組 .cn 分享 3行代碼 多元線性方程組

數學-線性代數-#2 用消元法解線性方程組

結合 單純 方框 法則 基本 步驟 滿足 原則 log 線性代數-#2 用消元法解線性方程組 #2實現了#1中的承諾,介紹了求解線性方程組的系統方法——消元法。 既然是一種系統的方法,其基本步驟可以概括如下: 1.將方程組改寫為增廣矩陣: 為了省去傳統消元法中反復出現但

線性方程組的直接解法

線性 set ani 結果 stream printf cpp 方程 ddl #include "stdafx.h" #include <iostream> #include <iomanip> #include <typeinfo.h>