Sum
HDU - 4704Input
2Output
2
2Sample Output
2Hint
1. For N = 2, S(1) = S(2) = 1. 2. The input file consists of multiple test cases.
根据题意我们可以容易的发现这题需要用隔板法,隔板法大家高中的时候应该都是学过。
这个题给你一个数n,把n分成k个数相加有几种,根据题意x1,x2...xk这么一个序列只要不同即可,也就是说数字可以重复
比如 5 = 1 + 1 + 3 和 5 = 1 + 3 + 1这两个可以算作两种不同的,那么就可以直接使用组合数,将数字n分解成n个1,那么就会有n-1个空,我们要把它分成k个数相加,需要插k-1个隔板,所以种类数就是C(n-1,k-1)
所以题目要我们求的就是C(n-1,0) + C(n-1,1) + C(n-1,2) + ... + C(n-1,k-1) ... + C(n-1,n-1) = 2^(n-1);
为什么等于2^n-1呢,这个公式的证明来自于二项式定理
利用二项式定理(a+b)^n=C(n,0)a^n+C(n,1)a^(n-1)*b+C(n,2)a^(n-2)*b2+…+C(n,n-2)a^2*b^(n-2)+C(n,n-1)a*b^(n-1)+C(n,n)*b^n
令a=b=1即得 C(n,0)+C(n,1)+C(n,2)+…+C(n,n-2)+C(n,n-1)+C(n,n)=2^n
接下来我们就要计算2^n-1,毫无疑问需要用快速幂取模,但是我们发现n的大小是10^100000,这时候就需要利用另一个有力的工具:费马小定理
我们通过费马小定理实现降幂的操作:
我们知道费马小定理是:设p是素数,a是任意整数且a不被p整除,则有
a^(p-1) ≡ 1(mod p)
所以我们发现这道题中p = 1e9+7, 2不被p整除,满足费马小定理,所以可以使用,那么它是如何实现降幂的呢?
下面我先举个栗子:
我们计算2^35(mod7)
因为2^35 = 2^(6*5+5) = (2^6)^5 * (2^5)
这是我们发现了2^(p-1)即2^6即2^(7-1),根据费马小定理
上式 = 1^5 * 2^5 = 2^5.
所以2^35 ≡ 2^5 (mod7) 我们就完成了对2^35的降幂,那么我们观察上面的过程
发现所谓降幂操作:我们只需要对指数取模(p-1)即可完成!!
对于题目我们以字符串的形式读入,然后一步一步加上每位乘10取模1e9+7-1即可得到我们降幂后的n,然后快速幂算 2^(n-1)即可
code:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int MOD = 1e9+7;
const int maxn = 1e5+10;
ll q_pow(ll a, ll b){
ll ans = 1LL;
while(b){
if(b & 1)
ans = ans * a % MOD;
b >>= 1;
a = a * a % MOD;
}
return ans % MOD;
}
ll getN(char s[]){
ll ans = 0;
int len = strlen(s);
for(int i = 0; i < len; i++){
ans = (10 * ans + s[i] - '0') % (MOD - 1);
}
return ans;
}
int main(){
char s[maxn];
while(scanf("%s",s) != EOF){
ll n = getN(s);
printf("%lld\n",q_pow(2,n-1));
}
return 0;
}