費馬小定理降冪--nkoj3687 整數拆分
阿新 • • 發佈:2018-12-29
P3687 整數拆分
時間限制 : - MS 空間限制 : 65536 KB 評測說明 : 時限1000ms 問題描述給你一個正整數N,F(x)表示把N拆分成x個正整數之和的方案數。
例如,當n=5時:
F(1)=1,方案為:{5}
F(2)=4,方案為:{1+4} {4+1} {2+3} {3+2}
F(3)=6,方案為:{1+1+3} {1+3+1} {3+1+1} {1+2+2} {2+1+2} {2+2+1}
F(4)=4,方案為:{1+1+1+2} {1+1+2+1} {1+2+1+1} {2+1+1+1}
F(5)=1,方案為:{1+1+1+1+1}
請你計算出F(1)+F(2)+......+F(N)
結果可能很大,mod 1,000,000,007 再輸出!
輸入格式
第一行,一個整數N
輸出格式
一行,一個整數,表示所求的結果
樣例輸入
5
樣例輸出
16
提示
對於50%的資料1<=N<=100
對於100%的資料1<=N<=10^100000
/* 考點:費馬小定理降冪 經觀察很容易推出答案是2^(n-1) mod 1000000007,設p=1000000007 因為p是質數,根據費馬小定理:a^(p-1) ≡1(mod p) 我們有: 2^(n-1)%p=2^((n-1)%(p-1)) %p */ #include<iostream> #include<cstdio> #include<cstring> using namespace std; const int mod=1e9+7; char str[100005]; long long Montgomery(long long a,long long b,long long mod)//快速冪 { long long ans=1; while(b>0) { if(b&1)ans=(ans*a)%mod; a=(a*a)%mod; b=b>>1; } return ans; } int main(){ long long i,ans,num=0; scanf("%s",str); int len=strlen(str); for(i=0;i<len;i++){ num=( num*10+(str[i]-'0') )% (mod-1);//將字元陣列轉換成整數 } //num=n%(mod-1) if(num==0) ans=Montgomery(2,mod-2,mod);//此時n=mod-1,求2^(mod-2) else ans=Montgomery(2,num-1,mod); printf("%I64d\n",ans); return 0; }
如果要輸入一個很大很大的數n,最後要輸出n模一個數的結果怎麼辦呢?
程式碼如下:
#include<iostream> #include<cstdio> #define LL long long using namespace std; const LL p =1000000007; void _read(LL &x){ char ch=getchar(); bool mark=false; for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true; for(x=0;isdigit(ch);ch=getchar())x=(x*10+ch-'0')%(p-1); //邊讀邊取模 if(mark)x=-x; } int main(){ LL n; _read(n); cout<<n%p; }