假如p是質數,且gcd(a,p)=1,那麼 a^(p-1)≡1(mod p)spa
也就是a^(p-1) %p=1code
聽說它是歐拉定理的一種特殊狀況,也就是blog
比較神奇,聽說很出名很出名很出名string
先回顧一下乘法逆元io
x的最小整數解稱爲a模m的逆元class
若是這個m是個質數,那麼費馬小定理就派上用場嘍gc
這個時候x的最小整數解是im
推導過程:db
只可意會不可言傳的樣子。img
例題是HDU4704,題意是:求1-n中,組成n的不一樣種數
用隔板法思考,在n個1裏面插隔板有幾種插法
結果是2^(n-1)
而後呢?就是計算它了,質數的範圍是1e6,那麼好,按題意取模
也就是求2^(n-1)%mod
費馬小定理a^b%c=a^(b%(c-1))%c
使用的前提是mod是個質數
對於任意天然數,當要求a^p%m時,就能夠利用費馬小定理化簡,只需求(a^(p%(m-1)))%m(p是素數)
記住這句話,題目就很顯然了
咱們將n拆成多個 a*(p-1) + k ,也就是2^n = 2^[a*(p-1) + k ] % mod = 2^k % mod
在這裏p直接等於mod,就那麼中括號的左半部分由於費馬小定理就化沒了,只剩下個k
要求的是2^(n-1),計算出k後,減一直接快速冪便可
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 const long long MOD=1000000007; 5 char s[1000005]; 6 long long cal(long long m) 7 { 8 int len=strlen(s); 9 long long ans=0; 10 for(int i=0;i<len;i++) 11 ans=(ans*10+s[i]-'0')%m; 12 return ans; 13 } 14 long long pow_mod(long long a,long long b) 15 { 16 long long ans=1; 17 while(b!=0) 18 { 19 if(b&1) ans=ans*a%MOD; 20 a=a*a%MOD; 21 b>>=1; 22 } 23 return ans; 24 } 25 int main() 26 { 27 while(scanf("%s",s)==1) 28 { 29 long long k=cal(MOD-1); 30 printf("%lld\n",pow_mod(2,k-1)); 31 } 32 return 0; 33 }