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<=10100000
当N=5的时候,我们可以想到将5分成1 1 1 1 1,那么根据题意则相当于将每i个数合为一个的总方案(0<=i<=n-1)
我们就可以发现题目就转化为了有N-1个空,在这n-1个空中放i个球的总方案
那么很明显,可以得到一个组合数的总和
因此用暴力可以发现规律,最终答案等于2^(n-1)
但是10的十万次方的数据,甚至都不能把输入数据直接用整数的形式存下来
因此我们可以想到使用费马小定理降幂
由于答案是2^(n-1) mod 1000000007,设p=1000000007
因为p是质数,根据费马小定理:a^(p-1) ≡1(mod p) 我们有:
由于答案是2^(n-1) mod 1000000007,设p=1000000007
因为p是质数,根据费马小定理:a^(p-1) ≡1(mod p) 我们有:
2^(p-1)%p=1
2^(n-1)%p=2^((n-1)%(p-1)) %p
2^(n-1)%p=2^((n-1)%(p-1)) %p
即在2的各次方中将2的p-1次方全部模掉,那么剩下的就是我们要求的答案了
#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
using namespace std;
const int mod=1e9+7;
char str[100005];
LL mg(LL a,LL b,LL mod){
LL ans=1;
while(b>0){
if(b&1)ans=(ans*a)%mod;
a=(a*a)%mod;
b=b>>1;
}
return ans;
}
int main(){
LL 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);
if(num==0)ans=mg(2,mod-2,mod);
else ans=mg(2,num-1,mod);
cout<<ans;
}
2270

被折叠的 条评论
为什么被折叠?



