費馬小定理(入門+內容+應用+例題)

費馬小定理新手入門+總結

縱有疾風起,人生不言棄。php

前言

最近新手的我作了幾個和快速冪有關的題目,發現他們還常常和費馬小定理聯繫在一塊兒,因此有必要寫一篇文章來總結一下費馬小定理,以便後面更好的學習。數組

內容介紹

費馬小定理是數論中的一個重要定理,再1636年提出。學習

​核心:若是p是一個質數,而且整數a不是p的倍數,則有公式:\(a^{p-1}\equiv1(mod\ p)\)ui

定理應用

那麼問題來了,這個定理該怎麼應用呢?spa

這裏舉一個題目來進行說明。code

Sum HDU - 4704get

這個題目大致的意思是說輸入一個數N,求N被拆分紅若干個正整數的結果,注意 1+2 和 2+1算做兩種。N很大,須要使用數組進行存儲。string

輸出的結果可能很大,須要mod 1e9+7,注意這個數是一個質數,正好符合費馬小定理的要求。it

題目解答

  1. 隔板原理+組合數求和公式io

    \(1-N\)有N個元素,每一個元素表明一個,分紅K個數,即在\((N-1)\)個空擋裏放置\(()(K-1)\)塊隔板(最多放置N-1個擋板)。

    即求組合數\(,C(0,N-1)+C(1,N-1)+...+C(N-1,N-1)\)的和,根據二項式定理,這個和爲\(2^{n-1}\)

  2. 使用費馬小定理

    由於N很大,因此須要使用費馬小定理來進行降冪

    \[ 2^{n-1}mod(p)=2^{n-1-k(p-1)+k(p-1)}mod(p)=2^{n-1-k(p-1)}mod(p)*2^{k*(p-1)}mod(p) \tag{2.1} \]

    又由於p是一個質數,且2和p互質,那麼就可使用費馬小定理了,即

    \[ 2^{k*(p-1)}mod(p)=1 \tag{2.2} \]

    這樣將\(公式(2.2)公式\)帶入到\(公式(2.1)公式\)中獲得

    \[ 2^{n-1}mod(p)=2^{n-1-k(p-1)}=2^{(n-1)mod(p-1)} \tag{2.3} \]

    因而計算就變得比較簡單了。

  3. 快速冪進行求取\(2^{(n-1)mod(p-1)}\)的值

    快速冪的複雜度爲\(O(lgN)\)

代碼展現

  • #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    
    using namespace std;
    typedef long long ll;
    const ll mod=1e9+7;
    const ll maxn=1e8;
    char str[maxn];
    
    ll qpow(ll a) //快速冪的模板
    {
      ll ans=1, base=2; //base存儲基數,這裏能夠調整不一樣的數
      while(a)
      {
          if(a&1)
          {
              ans=ans*base%mod;
          }
          base=(base*base)%mod; //注意這裏若是基數是2的狀況下,不能使用base=(base<<1)%mod
                                  //由於這裏有mod,因此寫法目前是惟一的,就是代碼中的寫法。
          a>>=1;
      }
      return ans%mod;
    }
    int main()
    {
      while(scanf("%s", str)!=EOF)
      {
          ll num=0, len=strlen(str);
          for(int i=0; i<len; i++)
              num=(num*10 + str[i]-'0') % (mod-1); //這就是對2的指數的化簡,使用費馬小定理
          printf("%lld\n", qpow(num-1));
      }
      return 0;
     }

總結

\[ 2^{p-1}=1(mod\ p) \]

  1. 費馬小定理最重要的一點是p(模數)必須是質數,而且與a(底數)互質,只有這樣才能使用。
  2. 使用這個定理的目的主要是下降計算的複雜度。
  3. 也能夠用於某些數論方面的題目,這個目前本身用的比較少,不是很清楚。

END

相關文章
相關標籤/搜索