• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            模運算及其應(yīng)用

            goal00001111搜集整理

             

            摘要:模運算在數(shù)論和程序設(shè)計中應(yīng)用很廣泛,從奇偶數(shù)的判別到素數(shù)的判別,從模冪運算到最大公約數(shù)的求法,從孫子問題到凱撒密碼問題,無不充斥著模運算的身影。本文從模運算的概念,性質(zhì),到模運算的基本應(yīng)用,較為全面的介紹了模運算及其編程方法。

            關(guān)鍵詞:模運算 程序設(shè)計 應(yīng)用

             

                   模運算在數(shù)論和程序設(shè)計中都有著廣泛的應(yīng)用,從奇偶數(shù)的判別到素數(shù)的判別,從模冪運算到最大公約數(shù)的求法,從孫子問題到凱撒密碼問題,無不充斥著模運算的身影。雖然很多數(shù)論教材上對模運算都有一定的介紹,但多數(shù)都是以純理論為主,對于模運算在程序設(shè)計中的應(yīng)用涉及不多。本文以c++語言為載體,對基本的模運算應(yīng)用進行了分析和程序設(shè)計,以理論和實際相結(jié)合的方法向大家介紹模運算的基本應(yīng)用。。

             

            基本理論:

            基本概念:

            給定一個正整數(shù)p,任意一個整數(shù)n,一定存在等式  n = kp + r
            其中k、r是整數(shù),且 0 ≤ r < p,稱呼kn除以p的商,rn除以p的余數(shù)。
            對于正整數(shù)p和整數(shù)a,b,定義如下運算: 
            取模運算:a % p(或a mod p),表示a除以p的余數(shù)。 

            p加法:(a + b) % p ,其結(jié)果是a+b算術(shù)和除以p的余數(shù),也就是說,(a+b) = kp +r,則(a + b) % p = r 

            p減法:(a-b) % p ,其結(jié)果是a-b算術(shù)差除以p的余數(shù)。 

            p乘法:(a * b) % p,其結(jié)果是 a * b算術(shù)乘法除以p的余數(shù)。 
            說明:

            1. 同余式:正整數(shù)a,bp取模,它們的余數(shù)相同,記做 a ≡ b % p或者a ≡ b (mod p)。

            2. n % p得到結(jié)果的正負(fù)由被除數(shù)n決定,p無關(guān)。例如:7%4 = 3 -7%4 = -3, 7%-4 = 3, -7%-4 = -3。

            基本性質(zhì):

            1)若p|(a-b),則a≡b (% p)。例如 11 ≡ 4 (% 7), 18 ≡ 4(% 7)

            2(a % p)=(b % p)意味a≡b (% p)

            3)對稱性:a≡b (% p)等價于b≡a (% p)

            4)傳遞性:若a≡b (% p)b≡c (% p) ,則a≡c (% p)

             

            運算規(guī)則:

            模運算與基本四則運算有些相似,但是除法例外。其規(guī)則如下:
                    (a + b) % p = (a % p + b % p) % p            
            1
                    (a - b) % p = (a % p - b % p) % p            
            2 
                    (a * b) % p = (a % p * b % p) % p            
            3
                   ab % p = ((a % p)b) % p                        
            4

            結(jié)合率: ((a+b) % p + c) % p = (a + (b+c) % p) % p  5

            ((a*b) % p * c)% p = (a * (b*c) % p) % p   6

            交換率: (a + b) % p = (b+a) % p                 7

            (a * b) % p = (b * a) % p                 8

            分配率: ((a +b)% p * c) % p = ((a * c) % p + (b * c) % p) % p  9

            重要定理:若a≡b (% p),則對于任意的c,都有(a + c) ≡ (b + c) (%p);(10

            a≡b (% p),則對于任意的c,都有(a * c) ≡ (b * c) (%p);(11

            a≡b (% p),c≡d (% p),則 (a + c) ≡ (b + d) (%p),(a - c) ≡ (b - d) (%p)

            (a * c) ≡ (b * d) (%p),(a / c) ≡ (b / d) (%p); 12

            a≡b (% p),則對于任意的c,都有ac≡ bc (%p);     13

             

            基本應(yīng)用:

            1.判別奇偶數(shù)

                   奇偶數(shù)的判別是模運算最基本的應(yīng)用,也非常簡單。易知一個整數(shù)n2取模,如果余數(shù)為0,則表示n為偶數(shù),否則n為奇數(shù)。

            C++實現(xiàn)功能函數(shù):

                   /*

            函數(shù)名:IsEven

            函數(shù)功能:判別整數(shù)n的奇偶性。能被2整除為偶數(shù),否則為奇數(shù)                        

            輸入值:int n,整數(shù)n

            返回值:bool,若整數(shù)n是偶數(shù),返回true,否則返回false

            */

            bool IsEven(int n)

            {

                return (n % 2 == 0);

            }

             

            2.判別素數(shù)

                   一個數(shù),如果只有1和它本身兩個因數(shù),這樣的數(shù)叫做質(zhì)數(shù)(或素數(shù))。例如 2,357 是質(zhì)數(shù),而 4689 則不是,后者稱為合成數(shù)或合數(shù)。

            判斷某個自然數(shù)是否是素數(shù)最常用的方法就是試除法:用比該自然數(shù)的平方根小的正整數(shù)去除這個自然數(shù),若該自然數(shù)能被整除,則說明其非素數(shù)。

            C++實現(xiàn)功能函數(shù):

                   /*

            函數(shù)名:IsPrime

            函數(shù)功能:判別自然數(shù)n是否為素數(shù)。                                                                         

            輸入值:int n,自然數(shù)n

            返回值:bool,若自然數(shù)n是素數(shù),返回true,否則返回false

            */

            bool IsPrime(unsigned int n)

            {

                unsigned maxFactor = sqrt(n); //n的最大因子

               

                for (unsigned int i=2; i<=maxFactor; i++)

                {

                         if (n % i == 0) //n能被i整除,則說明n非素數(shù)

                         {

                           return false;

                    }

                   }

                   return true;

            }

             

            3. 最大公約數(shù)

                   求最大公約數(shù)最常見的方法是歐幾里德算法(又稱輾轉(zhuǎn)相除法),其計算原理依賴于定理:gcd(a,b) = gcd(b,a mod b)

            證明:a可以表示成a = kb + r,則r = a mod b

            假設(shè)da,b的一個公約數(shù),則有d|a, d|b,而r = a - kb,因此d|r

            因此d(b,a mod b)的公約數(shù)

            假設(shè)d (b,a mod b)的公約數(shù),則d | b , d |r ,但是a = kb +r

            因此d也是(a,b)的公約數(shù)

            因此(a,b)(b,a mod b)的公約數(shù)是一樣的,其最大公約數(shù)也必然相等,得證。

            C++實現(xiàn)功能函數(shù):

            /*

            函數(shù)功能:利用歐幾里德算法,采用遞歸方式,求兩個自然數(shù)的最大公約數(shù)          

            函數(shù)名:Gcd

            輸入值:unsigned int a,自然數(shù)a

                    unsigned int b,自然數(shù)b

            返回值:unsigned int,兩個自然數(shù)的最大公約數(shù)

            */

            unsigned int Gcd(unsigned int a, unsigned int b)

            {

                if (b == 0)

                    return a;

                return Gcd(b, a % b);

            }

            /*

            函數(shù)功能:利用歐幾里德算法,采用迭代方式,求兩個自然數(shù)的最大公約數(shù)                  函數(shù)名:Gcd

            輸入值:unsigned int a,自然數(shù)a

                    unsigned int b,自然數(shù)b

            返回值:unsigned int,兩個自然數(shù)的最大公約數(shù)

            */

            unsigned int Gcd(unsigned int a, unsigned int b)

            {

                  unsigned int temp;

                while (b != 0)

                {

                    temp = a % b;

                    a = b;

                    b = temp;

                }

                return a;

            }

             

            6.模冪運算

                   利用模運算的運算規(guī)則,我們可以使某些計算得到簡化。例如,我們想知道3333^5555的末位是什么。很明顯不可能直接把3333^5555的結(jié)果計算出來,那樣太大了。但我們想要確定的是3333^5555%10),所以問題就簡化了。

                   根據(jù)運算規(guī)則(4ab % p = ((a % p)b) % p  ,我們知道3333^5555%10= 3^5555%10)。由于3^4 = 81,所以3^4%10= 1。

            根據(jù)運算規(guī)則(3 (a * b) % p = (a % p * b % p) % p ,由于5555 = 4 * 1388 + 3,我們得到3^5555%10=3^(4*1388) * 3^3)(%10=((3^(4*1388)%10* 3^3%10))(%10

            =1 * 7)(%10= 7

                   計算完畢。

                   利用這些規(guī)則我們可以有效地計算X^N(% P)。簡單的算法是將result初始化為1,然后重復(fù)將result乘以X,每次乘法之后應(yīng)用%運算符(這樣使得result的值變小,以免溢出),執(zhí)行N次相乘后,result就是我們要找的答案。

                   這樣對于較小的N值來說,實現(xiàn)是合理的,但是當(dāng)N的值很大時,需要計算很長時間,是不切實際的。下面的結(jié)論可以得到一種更好的算法。

                   如果N是偶數(shù),那么X^N =X*X^[N/2];

                   如果N是奇數(shù),那么X^N = X*X^(N-1) = X *X*X^[N/2];

            其中[N]是指小于或等于N的最大整數(shù)。

            C++實現(xiàn)功能函數(shù):

            /*

            函數(shù)功能:利用模運算規(guī)則,采用遞歸方式,計算X^N(% P)    

            函數(shù)名:PowerMod

            輸入值:unsigned int x,底數(shù)x

                    unsigned int n,指數(shù)n

                    unsigned int p,模p

            返回值:unsigned intX^N(% P)的結(jié)果

            */

            unsigned int PowerMod(unsigned int x, unsigned int n, unsigned int p)

            {

                if (n == 0)

                {

                          return 1;

                }

               

                unsigned int temp = PowerMod((x * x)%p, n/2, p); //遞歸計算(X*X^[N/2]

               

                if ((n & 1) != 0) //判斷n的奇偶性

                {

                         temp = (temp * x) % p;

                }

               

                return temp;

            }

             

            5.《孫子問題(中國剩余定理)

            在我國古代算書《孫子算經(jīng)》中有這樣一個問題:

            “今有物不知其數(shù),三三數(shù)之剩二,五五數(shù)之剩三,七七數(shù)之剩二,問物幾何?”意思是,“一個數(shù)除以32,除以53,除以72.求適合這個條件的最小數(shù)。”

            這個問題稱為“孫子問題”.關(guān)于孫子問題的一般解法,國際上稱為“中國剩余定理”.

            我國古代學(xué)者早就研究過這個問題。例如我國明朝數(shù)學(xué)家程大位在他著的《算法統(tǒng)宗》(1593年)中就用四句很通俗的口訣暗示了此題的解法:

            三人同行七十稀,五樹梅花甘一枝,七子團圓正半月,除百零五便得知。

            "正半月"暗指15"除百零五"的原意是,當(dāng)所得的數(shù)比105大時,就105、105地往下減,使之小于105;這相當(dāng)于用105去除,求出余數(shù)。

            這四句口訣暗示的意思是:當(dāng)除數(shù)分別是3、5、7時,用70乘以用3除的余數(shù),用21乘以用5除的余數(shù),用15乘以用7除的余數(shù),然后把這三個乘積相加。加得的結(jié)果如果比105大,就除以105,所得的余數(shù)就是滿足題目要求的最小正整數(shù)解。

            根據(jù)剩余定理,我把此種解法推廣到有n(n為自然數(shù))個除數(shù)對應(yīng)n個余數(shù),求最小被除數(shù)的情況。輸入n個除數(shù)(除數(shù)不能互相整除)和對應(yīng)的余數(shù),計算機將輸出最小被除數(shù)。

            C++實現(xiàn)功能函數(shù):

            /*

            函數(shù)名:ResidueTheorem

            函數(shù)功能:運用剩余定理,解決推廣了的孫子問題。通過給定n個除數(shù)(除數(shù)不能互相整除)和對應(yīng)的余數(shù),返回最小被除數(shù)                                                                         

            輸入值:unsigned int devisor[],存儲了n個除數(shù)的數(shù)組

                    unsigned int remainder[],存儲了n個余數(shù)的數(shù)組

                          int length,數(shù)組的長度

            返回值:unsigned int 最小被除數(shù)

            */

            unsigned int ResidueTheorem(const unsigned int devisor[], const unsigned int remainder[], int length)

            {

                unsigned int product = 1; //所有除數(shù)之乘積

                for (int i=0; i<length; i++)//計算所有除數(shù)之乘積 

                   {

                         product *= devisor[i];

                   }  

                  

                //公倍數(shù)數(shù)組,表示除該元素(除數(shù))之外其他除數(shù)的公倍數(shù)

                unsigned int *commonMultiple = new unsigned int(length);

                   for (int i=0; i<length; i++)//計算除該元素(除數(shù))之外其他除數(shù)的公倍數(shù) 

                   {

                         commonMultiple[i] = product / devisor[i];

                   } 

                  

                   unsigned int dividend = 0;  //被除數(shù),就是函數(shù)要返回的值

                   for (int i=0; i<length; i++)//計算被除數(shù),但此時得到的不是最小被除數(shù)

                   {

                         unsigned int tempMul = commonMultiple[i];

                         //按照剩余理論計算合適的公倍數(shù),使得tempMul % devisor[i] == 1

                         while (tempMul % devisor[i] != 1)

                         {

                        tempMul += commonMultiple[i];

                       }

                      

                       dividend += tempMul * remainder[i]; //用本除數(shù)得到的余數(shù)乘以其他除數(shù)的公倍數(shù)

                   }

               

                delete []commonMultiple;

                return (dividend % product);  //返回最小被除數(shù)

            }


            6.
            凱撒密碼

            凱撒密碼(caeser)是羅馬擴張時期朱利斯o凱撒(Julius Caesar)創(chuàng)造的,用于加密通過信使傳遞的作戰(zhàn)命令。

            它將字母表中的字母移動一定位置而實現(xiàn)加密。注意26個字母循環(huán)使用,z的后面可以堪稱是a。

            例如,當(dāng)密匙為k = 3,即向后移動3位時,若明文為”How are you!”,則密文為”Krz duh btx!”。

            凱撒密碼的加密算法極其簡單。其加密過程如下:

            在這里,我們做此約定:明文記為m,密文記為c,加密變換記為E(key1,m)(其中key1為密鑰),

            解密變換記為D(key2,m)key2為解密密鑰)(在這里key1=key2,不妨記為key)。

            凱撒密碼的加密過程可記為如下一個變換:cm+key (mod n (其中n為基本字符個數(shù))

            同樣,解密過程可表示為:mc+key (mod n (其中n為基本字符個數(shù))
            C++
            實現(xiàn)功能函數(shù):

            /*

            函數(shù)功能:使用凱撒密碼原理,對明文進行加密,返回密文                                          函數(shù)名:Encrypt

            輸入值:const char proclaimedInWriting[],存儲了明文的字符串

                    char cryptograph[],用來存儲密文的字符串

                          int keyey,加密密匙,正數(shù)表示后移,負(fù)數(shù)表示前移

            返回值:無返回值,但是要將新的密文字符串返回

            */

            void Encrypt(const char proclaimedInWriting[], char cryptograph[], int key)

            {

                const int NUM = 26; //字母個數(shù)

                int len = strlen(proclaimedInWriting);

               

                for (int i=0; i<len; i++)

                {

                         if (proclaimedInWriting[i] >= 'a' && proclaimedInWriting[i] <= 'z')

                         {//明碼是大寫字母,則密碼也為大寫字母

                        cryptograph[i] = (proclaimedInWriting[i] - 'a' + key) % NUM + 'a';

                    }

                         else if (proclaimedInWriting[i] >= 'A' && proclaimedInWriting[i] <= 'Z')

                         {//明碼是小寫字母,則密碼也為小寫字母

                        cryptograph[i] = (proclaimedInWriting[i] - 'A' + key) % NUM + 'A';

                    }

                    else

                    {//明碼不是字母,則密碼與明碼相同

                        cryptograph[i] = proclaimedInWriting[i];

                    }

                   }

                   cryptograph[len] = '\0';

            }

             

            /*

            函數(shù)功能:使用凱撒密碼原理,對密文進行解密,返回明文                                          函數(shù)名:Decode

            輸入值:char proclaimedInWriting[],用來存儲明文的字符串

                    const char cryptograph[],存儲了密文的字符串

                          int keyey,解密密匙,正數(shù)表示前移,負(fù)數(shù)表示后移(與加密相反)

            返回值:無返回值,但是要將新的明文字符串返回

            */

            void Decode(const char cryptograph[], char proclaimedInWriting[], int key)

            {

                const int NUM = 26; //字母個數(shù)

                int len = strlen(cryptograph);

               

                for (int i=0; i<len; i++)

                {

                         if (cryptograph[i] >= 'a' && cryptograph[i] <= 'z')

                         {//密碼是大寫字母,則明碼也為大寫字母,為防止出現(xiàn)負(fù)數(shù),轉(zhuǎn)換時要加個NUM

                      proclaimedInWriting[i] = (cryptograph[i] - 'a' - key + NUM) % NUM + 'a';

                    }

                         else if (cryptograph[i] >= 'A' && cryptograph[i] <= 'Z')

                         {//密碼是小寫字母,則明碼也為小寫字母

                        proclaimedInWriting[i] = (cryptograph[i] - 'A' - key + NUM) % NUM + 'A';

                    }

                    else

                    {//密碼不是字母,則明碼與明密相同

                        proclaimedInWriting[i] = cryptograph[i];

                    }

                   }

                   proclaimedInWriting[len] = '\0';

            }

             

                   模運算及其簡單應(yīng)用就先講到這了,其實模運算在數(shù)學(xué)及計算機領(lǐng)域的應(yīng)用非常廣泛,我這這里搜集整理了一些最最基本的情形,希望能夠起到一個拋磚引玉的作用,讓更多的人關(guān)注模運算,并及其應(yīng)用到更廣闊的領(lǐng)域中。      

             

            參考文獻:

            1.       《模運算》百度貼吧http://tieba.baidu.com/f?kz=30549931

            2.       《模運算性質(zhì)》 中國百科網(wǎng)

            http://www.chinabaike.com/article/316/shuxue/2007/20071005554776.html

            3.       《數(shù)據(jù)結(jié)構(gòu)與問題求解》 Mark Allen Weiss清華大學(xué)出版社

            4.       《孫子問題(中國剩余定理)

            http://hi.baidu.com/bjxiaoyao/blog/item/55ce951001d57d00213f2e30.html

            5.       《破解凱撒kaiser密碼》

            http://bbs.sei.ynu.edu.cn/viewthread.php?tid=5734

             

             

                  

             

                  

            Posted on 2008-10-25 11:51 夢想飛揚 閱讀(426) 評論(0)  編輯 收藏 引用
            一本大道久久a久久精品综合| 99久久精品九九亚洲精品| 一级女性全黄久久生活片免费| 亚洲精品国精品久久99热| 久久精品成人欧美大片| 久久99热国产这有精品| 久久夜色精品国产www| 久久午夜福利无码1000合集| 激情伊人五月天久久综合| 国产三级精品久久| 欧美亚洲色综久久精品国产 | 久久夜色精品国产| 久久亚洲精精品中文字幕| 久久久久国产成人精品亚洲午夜| 国产69精品久久久久久人妻精品| 伊人久久大香线蕉精品| 亚洲精品美女久久777777| 久久久久亚洲精品无码网址| 东京热TOKYO综合久久精品| 性做久久久久久久久久久| 狠狠色噜噜狠狠狠狠狠色综合久久| 欧美成人免费观看久久| 精品久久久久久无码人妻热| 国产一区二区三区久久| 久久综合88熟人妻| 久久久无码精品亚洲日韩京东传媒 | 久久亚洲高清观看| 69SEX久久精品国产麻豆| 成人综合久久精品色婷婷| 久久人人爽人人爽人人片AV东京热| 国产精品久久国产精品99盘| 久久A级毛片免费观看| 精品多毛少妇人妻AV免费久久| 四虎国产精品成人免费久久| 久久天天躁狠狠躁夜夜2020老熟妇 | 久久久免费观成人影院| 91精品无码久久久久久五月天| 国产精品久久一区二区三区| 久久精品蜜芽亚洲国产AV| 久久精品无码一区二区无码| 久久久久亚洲av无码专区导航 |