Description
Input
2
Output
2
Description
Input
2
Output
2
这道题目意思是给出一个数n,求把它分成1份,2份,3份...n份(分出的都是自然数)总共有多少种方法,数据很大结果对1e9+7取余。刚开始看到这题一脸茫然,后经过学习前人的经验,看出了一些端倪,毕竟是与数学有关的题目,不演算是看不出来的。首先列出了n=1到n=6的各种情况,发现满足一个等式:
ans=2^(n-1)mod(1e9+7),
是巧合还是必然?
原来这个问题是高中学概率时接触过的,就是一个隔板的问题,说n个东西,放n-1个隔板是个任取的问题,得C(n-1,n-1),(C这个符号是组合,括号里前者是C的下角标),放n-2个隔板,得C(n-1,n-2)...放一个隔板的话,就是C(n-1,1),将这些组合加起来,就是二项式展开,其中括号里是1+1(因为1的任意次方得1)。因此前面的式子不是偶然。附上二项式定理:
(a+b)^n=(n从0加到n)C(n,k)a^(n-k)*b^k.
知道了算什么之后就是怎么去算了。输入数据很大,只能用字符串输入,由于是求幂的运算,想到了快速幂,正好陈老师给过模版,拿来改成longlong 就可以用。考虑到幂数据很大,所以要用费马小定理来降幂。
上面就是费马小定理,字符串要循环取余,附上取余规则:
(a + b )mod n = (( a mod n)+( b mod n ))mod n;
( a – b)mod n=(( a mod n)- (b mod n) + n )mod n ;
ab mod n=(a mod n)( b mod n) mod n;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
#include <iostream>
#include <string.h>
#define mod 1000000007
using namespace std;
long long int quckpow(long long int m,long long int n,long long int k)
{
long long int b=1;
while(n>0)
{
if(n&1)b=(b*m)%k;
n=n>>1;
m=(m*m)%k;
}return b;
}
int main()
{
long long int sum,ans;
char c[100005];
while(cin>>c)
{ sum=0;
int l=strlen(c);
for(int i=0;i<l;i++)
sum=(sum*10+(c[i]-'0'))%(mod-1);
ans=quckpow(2,sum%(mod-1)-1,mod);
cout<<ans<<endl;
}
return 0;
}