HUD 4704 Sum 費馬小定理和快速冪
阿新 • • 發佈:2018-12-30
給定s(k)為k的劃分數
求劃分數的個數
比如當n=4時候
s(1)=(4)…………………………1
s(2)=(2,2)(1,3)(3,1)………3
s(3)=(1,1,2)(1,2,1)(2,1,1)……3
s(4)=(1,1,1,1)……………………1
所以是1+3+3+1=8
多列幾個會發現要求的是2^(n-1)
然後1<=n<10^100000太大了會爆
這時候有個定理叫 費馬小定理
費馬小定理(Fermat Theory)是數論中的一個重要定理,其內容為: 假如p是質數,且(a,p)=1,那麼
a(p-1)≡1(mod p)。即:假如a是整數,p是質數,且a,p互質(即兩者只有一個 公約數1),那麼a的(p-1)次方除以p的餘數恆等於1。
在這裡a=2,p=mod=1e9+7 剛好是一個質數
費馬小定理怎麼使用呢?
n=m+p
a^(n-1)%p=a^(m+p-1)%p
=(a^m*a^(p-1))%p
=(a^m%p)*(a^(p-1)%p)
=a^m%p
所以發現對於n來說mod-1是它的一個迴圈節我們可以對大數n取餘處理然後在快速冪就好了
ACcode:
#include <map> #include <queue> #include <cmath> #include <cstdio> #include <cstring> #include <stdlib.h> #include <iostream> #include <algorithm> const int mod=1e9+7; using namespace std; long long fpow(long long b){ long long a=2; long long ans=1; while(b){ if(b&1)///判斷奇偶性if(b%2==1) ans=(ans*a)%mod; a=(a*a)%mod; b=b>>1; } return ans; } int main(){ char s[1000000]; while(~scanf("%s",s)){ long long n=0; int len=strlen(s); for(int i=0;i<len;++i) n=(n*10+(s[i]-'0'))%(mod-1);///mod-1為迴圈節 // cout<<num<<'\12'; if(n==0)n=mod-1; printf("%I64d\n",fpow(n-1)); } return 0; }