簡(jiǎn)單算法實(shí)現(xiàn)之《中國(guó)剩余定理》

中國(guó)剩余定理
這個(gè)定理之前沒(méi)見(jiàn)過(guò),是在RSA算法原理(一)中提到的惯豆,想深入了解的可以去讀下。

故事背景
  • 韓信點(diǎn)兵

秦朝末年奔害,楚漢相爭(zhēng)楷兽。一次,韓信將1500名將士與楚王大將李鋒交戰(zhàn)华临⌒旧保苦戰(zhàn)一場(chǎng),楚軍不敵雅潭,敗退回營(yíng)瘪匿,漢軍也死傷四五百人,于是韓信整頓兵馬也返回大本營(yíng)寻馏。當(dāng)行至一山坡,忽有后軍來(lái)報(bào)核偿,說(shuō)有楚軍騎兵追來(lái)诚欠。只見(jiàn)遠(yuǎn)方塵土飛揚(yáng),殺聲震天漾岳。漢軍本來(lái)已十分疲憊轰绵,這時(shí)隊(duì)伍大嘩。韓信兵馬到坡頂尼荆,見(jiàn)來(lái)敵不足五百騎左腔,便急速點(diǎn)兵迎敵。他命令士兵3人一排捅儒,結(jié)果多出2名液样;接著命令士兵5人一排振亮,結(jié)果多出3名;他又命令士兵7人一排鞭莽,結(jié)果又多出2名坊秸。韓信馬上向?qū)⑹總冃迹何臆娪?073名勇士,敵人不足五百澎怒,我們居高臨下褒搔,以眾擊寡,一定能打敗敵人喷面。漢軍本來(lái)就信服自己的統(tǒng)帥星瘾,這一來(lái)更相信韓信是“神仙下凡”、“神機(jī)妙算”惧辈。于是士氣大振琳状。一時(shí)間旌旗搖動(dòng),鼓聲喧天咬像,漢軍步步進(jìn)逼算撮,楚軍亂作一團(tuán)。交戰(zhàn)不久县昂,楚軍大敗而逃肮柜。

題目就是:將軍點(diǎn)兵,三三數(shù)余2倒彰,五五數(shù)余3审洞,七七數(shù)余2。問(wèn)兵幾何待讳?

  • 孫子算經(jīng)

今有物芒澜,不知其數(shù),三三數(shù)之创淡,剩二痴晦,五五數(shù)之,剩三琳彩,七七數(shù)之誊酌,剩二,問(wèn)物幾何露乏?
答曰:二十三  
術(shù)曰:三三數(shù)之剩二碧浊,置一百四十,五五數(shù)之剩三瘟仿,置六十三箱锐,七七數(shù)之剩二,置三十劳较,并之驹止,得二百三十三浩聋,以二百一十減之,即得幢哨。凡三三數(shù)之剩一赡勘,則置七十,五五數(shù)之剩一捞镰,則置二十一闸与,七七數(shù)之剩一,則置十五岸售,即得践樱。

《孫子算經(jīng)》里給出了解決辦法

步驟一
除3余2 -> 取140
除5余3 -> 取63
除7余2 -> 取30
步驟二:
對(duì)上面取到的數(shù)求和
140 + 63 + 30 = 233
步驟三
用上面求出的結(jié)果減去210,就是結(jié)果
233 - 210 = 23
結(jié)果也就是23了

不過(guò)那140凸丸,63拷邢,30,還有210是怎么來(lái)的呢屎慢?這就涉及到中國(guó)剩余定理的算法原理了瞭稼。

中國(guó)剩余定理原理

#題目:
設(shè)要求的數(shù)為x,每個(gè)除法的結(jié)果分別為k1腻惠,k2环肘,k3,那么就有:
[1]  x / 3 = k1 + 2
[2]  x / 5 = k2 + 3
[3]  x / 7 = k3 + 2
1.對(duì)步驟一中的式子1求解過(guò)程為:取式子2和式子3中除數(shù)(5和7)的最小公倍數(shù)LCM(35)集灌,
然后把這個(gè)LCM作為x帶入式子1悔雹。如果LCM不能適應(yīng)式子1,就對(duì)LCM再加上一個(gè)LCM欣喧,
然后帶入式子1中......直到滿足式子1為止腌零。

按照這個(gè)求解過(guò)程,分別對(duì)3個(gè)式子求解唆阿,取到的結(jié)果為:35益涧,63,30
2.把上面求到的結(jié)果求和

35 + 63 + 30 = 128
3.這里對(duì)3個(gè)式子的除數(shù)取最小公倍數(shù)

3驯鳖,5饰躲,7的最小公倍數(shù)為105
然后用上面的結(jié)果減去這個(gè)最小公倍數(shù),就是結(jié)果了
128 - 105 = 23

這里估計(jì)有人要問(wèn)了:這個(gè)35也不是140臼隔,而且105也不等于210啊妄壶?摔握! 這個(gè)不用糾結(jié),這個(gè)跟古代數(shù)學(xué)的發(fā)展史有關(guān)嘛丁寄! 當(dāng)然氨淌,這是我瞎說(shuō)的泊愧,想要深挖的可以去研究下相關(guān)資料。

下面具體說(shuō)代碼實(shí)現(xiàn)

首先創(chuàng)建個(gè)model類盛正,類里面有除數(shù)和余數(shù)2個(gè)屬性删咱,然后提供一個(gè)便利構(gòu)造器,方便使用

@interface CRTModel : NSObject

@property (assign, nonatomic) NSInteger divider;

@property (assign, nonatomic) NSInteger remain;

+(instancetype)modelWithDivider:(NSInteger)divider
                         remain:(NSInteger)remain;

@end

@implementation CRTModel

+(instancetype)modelWithDivider:(NSInteger)divider remain:(NSInteger)remain
{
    CRTModel *model = [[self alloc] init];
    model.divider = divider;
    model.remain = remain;
    return model;
}

@end

還需要用到2個(gè)函數(shù)豪筝,最大公約數(shù)GCD和最小公倍數(shù)LCM

-(NSInteger)gcdOf:(NSInteger)a and:(NSInteger)b
{
    //這里使用歐幾里德算法
    static const NSInteger(^GCDRecursionBlock)(NSInteger,NSInteger) 
    = ^(NSInteger ra, NSInteger rb){
        if (!ra || !rb) return MAX(ra, rb);
        return GCDRecursionBlock(rb,ra%rb);
    };
    return GCDRecursionBlock(a,b);
}

//最小公倍數(shù)
-(NSInteger)lcmOf:(NSInteger)a and:(NSInteger)b
{
    return a * b / [self gcdOf:a and:b]; //最小公倍數(shù)等于兩數(shù)之積除以最大公約數(shù)
}

然后開(kāi)始實(shí)現(xiàn)算法

0.先創(chuàng)建3個(gè)Model痰滋,把題目"抄"一遍

CRTModel *model1 = [CRTModel modelWithDivider:3 remain:2];
CRTModel *model2 = [CRTModel modelWithDivider:5 remain:3];
CRTModel *model3 = [CRTModel modelWithDivider:7 remain:2];
1.取到算法中步驟1的結(jié)果:

-(NSInteger)getSubMinNumberOfDivider1:(NSInteger)divider1
                              divider2:(NSInteger)divider2
                           andDivider3:(NSInteger)divider3
                             remainOf3:(NSInteger)remainOf3
{
    NSInteger lcm = [self lcmOf:divider1 and:divider2];
    NSInteger result = lcm;
    while ((result % divider3) != remainOf3) {
        result += lcm;
    }
    return result;
}

NSInteger a = [self getSubMinNumberOfDivider1:model1.divider divider2:model2.divider andDivider3:model3.divider remainOf3:model3.remain];
NSInteger b = [self getSubMinNumberOfDivider1:model2.divider divider2:model3.divider andDivider3:model1.divider remainOf3:model1.remain];
NSInteger c = [self getSubMinNumberOfDivider1:model3.divider divider2:model1.divider andDivider3:model2.divider remainOf3:model2.remain];
2.求和

NSInteger sum = a + b + c;
3.求全部除數(shù)的最小公倍數(shù),然后求結(jié)果

//使用"更相減損術(shù)"
NSInteger lcmOfAll = 
    [self lcmOf:[self lcmOf:model1.divider and:model2.divider] and:model3.divider];
    
//求結(jié)果
NSInteger result = sum - lcmOfAll;
NSLog(@"計(jì)算結(jié)果為:%ld + %ld * k (k為自然數(shù))",result,lcmOfAll);    

算法代碼已經(jīng)上傳GitHub:
https://github.com/Bluelich/MyBlogCode/tree/master/CRTAlgorithm

就這么多了续崖。這是我昨晚回顧RSA加密時(shí)候看到的敲街,剛好就學(xué)習(xí)下了,其實(shí)想再?gòu)?fù)習(xí)下歐拉函數(shù)什么的严望,都忘光了多艇! 有時(shí)間就搞!像吻!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末峻黍,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拨匆,更是在濱河造成了極大的恐慌姆涩,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涮雷,死亡現(xiàn)場(chǎng)離奇詭異阵面,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)洪鸭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門样刷,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人览爵,你說(shuō)我怎么就攤上這事置鼻。” “怎么了蜓竹?”我有些...
    開(kāi)封第一講書人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵箕母,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我俱济,道長(zhǎng)嘶是,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任蛛碌,我火速辦了婚禮聂喇,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己希太,他們只是感情好克饶,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著誊辉,像睡著了一般矾湃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上堕澄,一...
    開(kāi)封第一講書人閱讀 52,696評(píng)論 1 312
  • 那天邀跃,我揣著相機(jī)與錄音,去河邊找鬼奈偏。 笑死坞嘀,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的惊来。 我是一名探鬼主播丽涩,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼裁蚁!你這毒婦竟也來(lái)了矢渊?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤枉证,失蹤者是張志新(化名)和其女友劉穎矮男,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體室谚,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡毡鉴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了秒赤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片猪瞬。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖入篮,靈堂內(nèi)的尸體忽然破棺而出陈瘦,到底是詐尸還是另有隱情,我是刑警寧澤潮售,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布痊项,位于F島的核電站,受9級(jí)特大地震影響酥诽,放射性物質(zhì)發(fā)生泄漏鞍泉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一肮帐、第九天 我趴在偏房一處隱蔽的房頂上張望咖驮。 院中可真熱鬧,春花似錦、人聲如沸游沿。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诀黍。三九已至,卻和暖如春仗处,著一層夾襖步出監(jiān)牢的瞬間眯勾,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工婆誓, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吃环,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓洋幻,卻偏偏與公主長(zhǎng)得像郁轻,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子文留,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容

  • 《我親愛(ài)的朋友們》作為TvN2016特別制作好唯,開(kāi)創(chuàng)了一個(gè)新領(lǐng)域:老年人和他們的故事,同樣走溫情路線燥翅,與請(qǐng)回答系列不...
    粉考拉工作室閱讀 764評(píng)論 0 0
  • 《從0到1》已經(jīng)火到創(chuàng)業(yè)者必讀骑篙。我雖不為一個(gè)創(chuàng)業(yè)者,但有心成為一個(gè)為社會(huì)創(chuàng)造財(cái)富的人森书,也學(xué)習(xí)了一番靶端。 不得不說(shuō),有...
    知奇者也閱讀 234評(píng)論 0 0