1. 程式人生 > >1079 中國剩餘定理

1079 中國剩餘定理

#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;
int a[12];
int b[12];
int main(){
	
	int n,maxa=0,ia,kvalue;
	cin>>n;
	for(int i=0;i<n;i++){
		cin>>a[i];
		cin>>b[i];
		if(a[i]>maxa){
			maxa=a[i];
			ia=b[i];
		}
	} 
	for(int k=1;k<=maxa;k++){
		for(int i=0;i<n;i++){
			if(!(k%a[i]==b[i])){
				break;
			}
			if(i==n-1){
				cout<<k;
				return 0;
			}
		}
	}
	for(int k=1;;k++){
		kvalue=k*maxa+ia;
		for(int i=0;i<n;i++){
			if(!(kvalue%a[i]==b[i])){
				break;
			}
			if(i==n-1){
				cout<<kvalue;
				return 0;
			}
		}
	}
	return 0;
}

---------------------------------------------------------------------------------------------

中國剩餘定理

  在《孫子算經》中有這樣一個問題:“今有物不知其數,三三數之剩二(除以3餘2),五五數之剩三(除以5餘3),七七數之剩二(除以7餘2),問物幾何?”這個問題稱為“孫子問題”,該問題的一般解法國際上稱為“中國剩餘定理”。具體解法分三步:

    1. 找出三個數:從3和5的公倍數中找出被7除餘1的最小數15,從3和7的公倍數中找出被5除餘1 的最小數21,最後從5和7的公倍數中找出除3餘1的最小數70。
    2. 用15乘以2(2為最終結果除以7的餘數),用21乘以3(3為最終結果除以5的餘數),同理,用70乘以2(2為最終結果除以3的餘數),然後把三個乘積相加15∗2+21∗3+70∗215∗2+21∗3+70∗2得到和233。
    3. 用233除以3,5,7三個數的最小公倍數105,得到餘數23,即233%105=23233%105=23。這個餘數23就是符合條件的最小數。

  就這麼簡單。我們在感嘆神奇的同時不禁想知道古人是如何想到這個方法的,有什麼基本的數學依據嗎?

  我們將“孫子問題”拆分成幾個簡單的小問題,從零開始,試圖揣測古人是如何推匯出這個解法的。

  首先,我們假設n1n1是滿足除以3餘2的一個數,比如2,5,8等等,也就是滿足3∗k+2(k>=0)3∗k+2(k>=0)的一個任意數。同樣,我們假設n2n2是滿足除以5餘3的一個數,n3n3是滿足除以7餘2的一個數。

  有了前面的假設,我們先從n1n1這個角度出發,已知n1n1滿足除以3餘2,能不能使得n1+n2n1+n2的和仍然滿足除以3餘2?進而使得n1+n2+n3n1+n2+n3的和仍然滿足除以3餘2?

  這就牽涉到一個最基本數學定理,如果有a%b=ca%b=c,則有(a+k∗b)%b=c(k為非零整數)(a+k∗b)%b=c(k為非零整數),換句話說,如果一個除法運算的餘數為cc,那麼被除數與kk倍的除數相加(或相減)的和(差)再與除數相除,餘數不變。這個是很好證明的。

  以此定理為依據,如果n2n2是3的倍數,n1+n2n1+n2就依然滿足除以3餘2。同理,如果n3n3也是3的倍數,那麼n1+n2+n3n1+n2+n3的和就滿足除以3餘2。這是從n1n1的角度考慮的,再從n2n2,n3n3的角度出發,我們可推匯出以下三點:

    1. 為使n1+n2+n3n1+n2+n3的和滿足除以3餘2,n2n2和n3n3必須是3的倍數。
    2. 為使n1+n2+n3n1+n2+n3的和滿足除以5餘3,n1n1和n3n3必須是5的倍數。
    3. 為使n1+n2+n3n1+n2+n3的和滿足除以7餘2,n1n1和n2n2必須是7的倍數。

  因此,為使n1+n2+n3n1+n2+n3的和作為“孫子問題”的一個最終解,需滿足:

    1. n1n1除以3餘2,且是5和7的公倍數。
    2. n2n2除以5餘3,且是3和7的公倍數。
    3. n3n3除以7餘2,且是3和5的公倍數。

  所以,孫子問題解法的本質是從5和7的公倍數中找一個除以3餘2的數n1n1,從3和7的公倍數中找一個除以5餘3的數n2n2,從3和5的公倍數中找一個除以7餘2的數n3n3,再將三個數相加得到解。在求n1n1,n2n2,n3n3時又用了一個小技巧,以n1n1為例,並非從5和7的公倍數中直接找一個除以3餘2的數,而是先找一個除以3餘1的數,再乘以2。也就是先求出5和7的公倍數模3下的逆元,再用逆元去乘餘數。

  這裡又有一個數學公式,如果a%b=ca%b=c,那麼(a∗k)%b=a%b+a%b+…+a%b=c+c+…+c=k∗c(k>0)(a∗k)%b=a%b+a%b+…+a%b=c+c+…+c=k∗c(k>0),也就是說,如果一個除法的餘數為cc,那麼被除數的kk倍與除數相除的餘數為k∗ck∗c。展開式中已證明。

  最後,我們還要清楚一點,n1+n2+n3n1+n2+n3只是問題的一個解,並不是最小的解。如何得到最小解?我們只需要從中最大限度的減掉掉3,5,7的公倍數105即可。道理就是前面講過的定理“如果a%b=ca%b=c,則有(a−k∗b)%b=c(a−k∗b)%b=c”。所以(n1+n2+n3)%105(n1+n2+n3)%105就是最終的最小解。

#include <stdio.h>

int main(int argc, const char * argv[])
{
    int N, i = 0, j = 0;
    int P[11], M[11];
    long long sum = 0, K, acc = 1;
    scanf("%d", &N);
    for (; i < N; i++)
    {
        scanf("%d %d", P + i, M + i);
        acc *= P[i];
    }

    for (i = 0; i < N; i++)
    {
        for (j = 1; j < 100000; j++)
        {
            if (acc / P[i] * j % P[i] == 1)
            {
                sum += acc / P[i] * j * M[i];
                break;
            }
        }
    }

    K = sum % acc;
    printf("%lld\n", K);
    return 0;
}

相關推薦

51nod 1079 中國剩餘定理 模板

一個正整數K,給出K Mod 一些質數的結果,求符合條件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合條件的最小的K = 23。 Input 第1行:1個數N表示後面輸入的質數及模的數量。(2 <= N <=&

51nod 1079 中國剩餘定理模板

中國剩餘定理就是同餘方程組除數為質數的特殊情況 我直接用同餘方程組解了。 記得exgcd後x要更新 還有先更新b1再更新m1,順序不能錯!!(不然會影響到b1的更新) #include<c

51 Nod 1079 中國剩餘定理(孫子定理

1079 中國剩餘定理 一個正整數K,給出K Mod 一些質數的結果,求符合條件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合條件的最小的K = 23。  收起 輸入 第1行:1個數N表示後面輸入的質數及模的數量。(2 <= N

51nod 1079 中國剩餘定理 模板

一個正整數K,給出K Mod 一些質數的結果,求符合條件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合條件的最小的K = 23。 Input 第1行:1個數N表示後面輸入的質數及模的數量。(2 <= N <= 10) 第

1079 中國剩餘定理

#include<iostream> #include<cstring> #include<algorithm> using namespace std; int a[12]; int b[12]; int main(){ int

【51 nod 1079 中國剩餘定理

一個正整數K,給出K Mod 一些質數的結果,求符合條件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合條件的最小的K = 23。 Input

[51Nod](1079)中國剩餘定理 ---- 數論

一個正整數K,給出K Mod 一些質數的結果,求符合條件的最小的K。例如,K % 2 = 1, K % 3 = 2, K % 5 = 3。符合條件的最小的K = 23。 Input 第1行:1個數N表示後面輸入的質數及模的數量。(2 <= N &l

51nod:1079 中國剩餘定理(數學)

該演算法用口訣表達是:“三人同行七十稀,五樹梅花廿一枝,七子團圓正半月,除百零五便得知。”意思是:每3個一數最後剩1個就取5和7的公倍數70(先讓他剩1,再用定理2),那麼“三三數之剩二個”,就取二倍個70得140(定理2);每5個一數最後剩1個就取3和7的公倍數21,那麼“五五數之剩三個” ,就取三倍個2

51nod 1079中國剩餘定理

基準時間限制:1 秒 空間限制:131072 KB 分值: 0 難度:基礎題 收藏 關注一個正整數K,給出K Mod 一些質數的結果,求符合條件的最小的K。例如,K % 2 = 1, K % 3 = 2

poj 2891 Strange Way to Express Integers 中國剩餘定理模板

Description   Elina is reading a book written by Rujia Liu, which introduces a strange way to express non-negative integers. The way is descr

Poj 1006 Biorhythms 中國剩餘定理

Description Some people believe that there are three cycles in a person's life that start the day he or she is born. These three cycles are the phys

Hdu 1573 X問題 中國剩餘定理模板

  Problem Description 求在小於等於N的正整數中有多少個X滿足:X mod a[0] = b[0], X mod a[1] = b[1], X mod a[2] = b[2], …, X mod a[i] = b[i], … (0 < a[i] <=

Hdu 3575 Hello Kiki 中國剩餘定理模板

Problem Description One day I was shopping in the supermarket. There was a cashier counting coins seriously when a little kid running and singing "門

中國剩餘定理poj1006

題意就是給出23,28,33三個週期,輸入三個餘數和起始時間,問下一個共同週期。 中國剩餘定理模板題 中國剩餘定理: mi=n1*n2*...*n(i-1)*n(i+1)*...*ni ci=mi ( mi^-1 mod ni ) a≡(a1c1+a2c2+...+akck)(mod n)

擴充套件歐幾里得及中國剩餘定理

Exgcd 擴充套件歐幾里得 void exgcd(int a,int b,int &x,int &y){ if(!b){x=1,y=0;return;} exgcd(b,a%b,x,y);b-=y*(a/b); } 對於 \(gcd(a,b)=g\) ,\(a\time

中國剩餘定理的五種解法

原文地址:http://blog.sina.com.cn/s/blog_a6f9a3b60101favb.html 一、列舉法 二、解不定方程法 三、逐級滿足法 四、化為相同除數的同餘式法、 五、才用到典經的、不同除數的同餘式組解法     現將陳

學習筆記 - 中國剩餘定理&擴充套件中國剩餘定理

中國剩餘定理&擴充套件中國剩餘定理 NOIP考完回機房填坑    ◌ 中國剩餘定理 處理一類相較擴充套件中國剩餘定理更特殊的問題:   在這裡要求 對於任意i,j(i≠j),gcd(mi,mj)=1 (就是互素) 不互素的話就只能用擴充套件

poj1006 Biorhythms【中國剩餘定理/暴力】

Biorhythms Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 14507

HDU 3430 Shuffling(置換群+中國剩餘定理)

Shuffling Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 548 &n

bzoj 1573 X問題【擴充套件中國剩餘定理

擴充套件中國剩餘定理的板子,合併完之後算一下範圍內能取幾個值即可(記得去掉0) #include<iostream> #include<cstdio> #include<cmath> using namespace std; const int N=15; int T,n