1. 程式人生 > >擴充套件歐幾里德演算法模版題(求逆元+分析+題目)HDU1576 A/B

擴充套件歐幾里德演算法模版題(求逆元+分析+題目)HDU1576 A/B

首先給大家普及一下什麼是擴充套件歐幾里德演算法,它是由歐幾里德演算法演變的,即我們常說的輾轉相除法。

程式碼如下: int gcd(int a,int b){ return b?gcd(b,a%b):a; } 那麼對於不完全為0的非負整數,a,b,gcd(a,b)表示a,b的最大公約數,必然存在整數對x,y使得 gcd(a,b)=ax+by

求解 x,y的方法的理解

設 a>b。 1,顯然當 b=0,gcd(a,b)=a。此時 x=1,y=0; 2,a>b>0 時 設 ax1+ by1= gcd(a,b); bx2+ (a mod b)y2= gcd(b,a mod b); 根據樸素的
歐幾里德
原理有 gcd(a,b) = gcd(b,a mod b); 則:ax1+ by1= bx2+ (a mod b)y2; 即:ax1+ by1= bx2+ (a - [a / b] * b)y2=ay2+ bx2- [a / b] * by2; 也就是ax1+ by1 == ay2+ b(x2- [a / b] *y2); 根據恆等定理得:x1=y2; y1=x2- [a / b] *y2; 這樣我們就得到了求解 x1,y1 的方法:x1,y1 的值基於 x2,y2. 上面的思想是以遞迴定義的,因為 gcd 不斷的遞迴求解一定會有個時候 b=0,所以遞迴可以結束,最後通過線性關係求出最初的x,y。 擴充套件歐幾里德演算法

 程式碼一如下:

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 t=x;x=y;y=t-a/b*y;
    return r;
}


 程式碼二如下:
int gcd(int a,int b,int &x,int &y){
    if (b==0){
        x=1,y=0;
        return a;
    }
    int q=gcd(b,a%b,y,x);
    y-=a/b*x;
    return q;
}



//遞迴最底層必定是a==gcd(a,b),所以x==1,b*y任意,令y=0,方便求解。 通過以上介紹的相鄰兩層遞迴之間線性關係,求出最初的x,y。

//找到一組數對x,y使得等式成立,但並不是最簡的整數,也不是非負的。下面的題目會涉及到。

A/B

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4753    Accepted Submission(s): 3701


Problem Description 要求(A/B)%9973,但由於A很大,我們只給出n(n=A%9973)(我們給定的A必能被B整除,且gcd(B,9973) = 1)。
Input 資料的第一行是一個T,表示有T組資料。
每組資料有兩個數n(0 <= n < 9973)和B(1 <= B <= 10^9)。
Output 對應每組資料輸出(A/B)%9973。
Sample Input 2 1000 53 87 123456789
Sample Output 7922 6060(之前寫的思路簡直就是扯淡,現在終於找到了方向)

思路:一個很大的數,在進行+、* 運算時,不斷的取餘是不影響結果的,但是 “-” 會出現負數,只要+mod在再%mod就行了,但是 /(除法)需要求逆元。所以這個就是個模板題。


程式碼如下:

思路一(正解):

#include <stdio.h>  
#include <stdlib.h>  
  
#define m 9973  
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 t=x;x=y;y=t-a/b*y;
    return r;
}
  
int main()  
{  
    int n,b,t,x,y;  
    scanf("%d",&t);  
  
    while(t--)  
    {  
        scanf("%d%d",&n,&b);  
        exGcd(b,m,x,y);  
        x=(x%m+m)%m;  //預設
        printf("%d\n",(x*n)%m);  //正常情況這裡要求x*A的,但是A比較大給了A%m取餘了。
    }  
    return 0;  
}

思路二:
//當然也可以從原理上分析這個題目因為A%B==0,假設A/B=T;模擬一下T的值就可以了,易犯錯誤(A/B)%9973!=(A%9973)/(B%9973)

#include<stdio.h>


int main()
{
	long long a,b;
	int k=9973;
	long long w;
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%I64d%I64d",&a,&b);
		int t=1;
		while(w%k!=a)
			w=(t++)*b;
		printf("%I64d\n",(t-1)%k);
	}
	return 0;
 } 


相關推薦

擴充套件演算法模版+分析+題目HDU1576 A/B

首先給大家普及一下什麼是擴充套件歐幾里德演算法,它是由歐幾里德演算法演變的,即我們常說的輾轉相除法。 程式碼如下: int gcd(int a,int b){ return b?gcd(b,a%b):a; } 那麼對於不完全為0的非負整數,a,b,gcd(a,b

同餘方程擴充套件演算法

同餘方程 時間限制: 1 Sec  記憶體限制: 128 MB 題目描述 求關於 x 的同餘方程 ax ≡ 1 (mod b)的最小正整數解。 輸入 輸入只有一行,包含兩個正整數 a, b,用一個空格隔開。 輸出 輸出只有一行,包含

caioj 1153 擴充套件演算法解不定方程

模板題 注意exgcd函式要稍微記一下 #include<cstdio> #include<cctype> #include<algorithm> #define

數論-擴充套件演算法

找出一對整數(x,y),使得ax+by=gcd(a,b)。注意,這裡的x和y不一定是正數,也可能是負數或者0.例如,gcd(6,15)=3,6*3-15*1=3,其中,x=3,y=-1.這個方程還有其他解,如x=-2,y=1。 用數學歸納法並不難證明演算法的正確性。此處略去

擴充套件演算法求解線性同餘方程

 歐幾里德演算法  歐幾里德演算法又稱輾轉相除法,用於計算兩個整數a,b的最大公約數。其計算原理依賴於下面的定理:  定理:gcd(a,b) = gcd(b,a mod b)  證明:a可以表示成a = kb + r,則r = a mod b  假設d是a,b的一個公約數,則

演算法的推導與證明 || 擴充套件演算法的解釋說明

序言:      當博主第一次見到歐幾里德演算法時,我是不屑一顧的,由於模板比較好背,所以也沒有仔細研究過其中的數學原理.這段時間突然喜歡上了數學,碰巧同學講了一下基礎數論,就去聽了一聽. 由於博主數學基礎和學習能力都比較差,沒有立即消化其中的知識,於是研究

擴充套件演算法 遞迴和非遞迴實現及證明

關於歐幾里得演算法,貝祖等式,擴充套件歐幾里得演算法,Wikipedia的解釋非常非常詳細了。 另外,看了好多別人優秀的總結,我認為最詳盡的就是ACM之家的總結。 這裡自己再總結一次…實際上就是把別人總結的,我認為有助於自己理解的內容copy過來,再加上

gcd演算法/extgcd擴充套件演算法以及在解不定方程中的應用

這個應該是我在noip前就應該會的東西 ,但是當時也許只是記下了程式碼吧 ,現在有諸多的不理解。後來藉著書和幾篇部落格弄懂了並小證了一下,鑑於網上有些部落格關於這個的寫的真的不好看,所以自己來總結一下,順帶以後也能看。 順帶一提,gcd(a,b)表示a,b的最

#數論# 演算法擴充套件演算法 、費馬小、求解ing

歐幾里德求gcd(輾轉相除法): 定理: gcd(a, b) = gcd(b, a % b) 兩個正整數a和b(a>b),它們的最大公約數等於a除以b的餘數c和b之間的最大公約數 證明: a可以表示成a = kb + r,則r = a %

擴充套件演算法乘法C語言版

#include <stdio.h>   int ExtendedEuclid( int f,int d ,int *result);   int main()   {   int x,y,z;   z = 0;   printf("輸入

演算法擴充套件演算法、乘法

最近看了一本書《程式設計師》裡面說的一個面試題: 求兩個數的最大公約數: SoEasy的題目看過C 的人都知道怎麼寫這個程式 1.傳統方法:窮舉 #include <math.h>int main(){int m=1970,n=1066,p=0;p=m<n?m:n;for(;p>=1

擴充套件演算法Java實現和青蛙相遇

問題銜接: http://poj.org/problem?id=1061 Description 兩隻青蛙在網上相識了,它們聊得很開心,於是覺得很有必要見一面。它們很高興地發現它們住在同一條緯度線上,於是它們約定各自朝西跳,直到碰面為止。可是它們出發之前忘記了一件很重要

HDU 1576 A/B 擴充套件演算法

解決該題的關鍵是: 1、瞭解擴充套件歐幾里德演算法,可以運用其解出gcd(a,b)=ax1+by1中的x1、y1的值 2、由題可得以下內容: n=A%9973,則n=A-A/9973*9973。又A/B=x,則A=Bx。所以Bx-A/9973*9973=n。即Bx-997

擴充套件演算法解二元一次不定方程

擴充套件歐幾里德演算法: 已知兩個不完全為 0 的非負整數 a,b,必然存在整數對 x,y ,使它們滿足貝祖等式: 解一定存在,根據數論中的相關定理。下面給出程式碼: int extgcd(int a, int b, int& x, int& y)

輾轉相除法 費馬小定理 尤拉定理 擴充套件演算法簡介

證明:對於(2),p是素數,a是整數且gcd(a,p)=1即他們的最大公約數是1。由於a, 2a, 3a, ……,(p-1)a 模p的餘數都不相同。否則若(i*a) mod p=(j*a) mod p其中 1 =< i < j <= p-1 則p|(j-i)*a, 而gcd(a,p)=1,那

擴充套件演算法-HDU2669

The Sky is Sprite.  The Birds is Fly in the Sky.  The Wind is Wonderful.  Blew Throw the Trees  Trees are Shaking, Leaves are Fal

演算法學習——演算法&擴充套件演算法

最大公約數/歐幾里德演算法(gcd) 歐幾里德演算法又稱輾轉相除法,證明可以度娘。 個人簡單腦部就是a和b兩個數的模還是a和b的最大公約數 int型別  int gcd(int a, int b) {return a%b==0?b:gcd(b,a%b);} long l

擴充套件演算法乘法

計算乘法逆元,比如3mod8的乘法逆元為3 是如何用歐幾里得演算法計算的呢??? 數對 x,y ,使得 gcd(a,b)=ax+by。 c++語言實現: #include <iostream&

擴充套件演算法

新博文地址:  [狀態轉移思想解讀:歐幾里德演算法及擴充套件](http://blog.csdn.net/sunliymonkey/article/details/46755983) 歐幾里德是用來求最大公約數的,可以把它看成是狀態轉移, 對任意兩個數a,b(a>

最大公因子輾轉相除法原理擴充套件演算法

while(n != 0) { r = m % n; m = n; n = r; } printf("Their greatest common divisor is %d.\n", m);