1. 程式人生 > >【例題】【費馬小定理(降冪)、遞推】NKOJ 3687 整數拆分

【例題】【費馬小定理(降冪)、遞推】NKOJ 3687 整數拆分

NKOJ 3687 整數拆分
時間限制 : - 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

思路:
1、先求通項公式
設f[i][j]表示將i分為j個正整數的方案數
則在f[i][j]種方案中,可分為兩類,第一類可由f[i-1][j-1]各方案加一項1所得,如f[5][3]中{3+1+1} {1+3+1} {1+1+3} {1+2+2} {2+1+2} {2+2+1} 1、2、6方案可由f[4][2]:{3+1} {1+3} {2+2} 三種方案加一項1所得,第二類可由f[i-1][j]各方案中一項加上1所得,如f[5][3]中 3、4、5方案可由f[4][3]: {1+2+1} {2+1+1} {1+2+1} 得到。
所以得到遞推式:f[i][j]=f[i-1][j-1]+f[i-1][j];
即楊輝三角…..
所以通項公式為ans=2^(n-1)%d d=1,000,000,007;

2、注意到1<=N<=10^100000
所以需要降冪
根據費馬小定理推論:(a^b%p=a^(b%(p-1))%p)
設m=n%(d-1) d=1,000,000,007;
則ans=2^(m-1)%d;

程式碼:

#include<cstdio> 
#include<iostream> 
using namespace std; 
#define ll long long  
const ll d=1000000007; 

ll power(ll a,ll b,ll c) 
{ 
    a%=c; 
    ll ans=1; 
    while(b) 
    { 
        if
(b&1) ans=(ans*a)%c; b>>=1; a=(a*a)%c; } return ans; } int main() { string a;cin>>a; int len=a.length(); ll m=0; for(int i=0;i<len;i++) m=(m*10+a[i]-'0')%(d-1); if(m==0) m=d-1; printf("%I64d",power(2,m-1,d)); }