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));
}