您的位置:首页 > 其它

HDU 4704Sum(费马小定理+快速幂)

2013-08-23 15:57 274 查看


Sum

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)

Total Submission(s): 343    Accepted Submission(s): 182


Problem Description



 

Sample Input

2

 

Sample Output

2
Hint
1. For N = 2, S(1) = S(2) = 1.

2. The input file consists of multiple test cases.

 

Source

2013 Multi-University Training Contest
10

 

                    题目大意:给你一个n,问你把他分成a1+a2+a3+...+an有多少种。直接用插隔板法解决,把n分成n个1.里面产生了n-1个空然后就可以C(n-1,0)+C(n-1,1)+....+C(n-1,n-1).组合数相加根据结论是2^(n-1).

            解题思路:n最大是10^100000.开始准备用Java写,但是突然意识到自己换了Win8什么JDK都还没装。果断转换思路,而且Java能存这么大的数么。。没试过。 使用费马小定理a^(p-1)%p==1,然后a^x%p直接转换成了a^(x%(p-1))%p不过p需要是素数,10^9+7是个很好的提示。然后开始就是先算指数ans=x%(p-1)不过注意求得是2^(n-1).所以就需要减1.然后剩下的就是快速幂取模。具体见代码。

            题目地址:Sum

AC代码:
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
char s[100005];
__int64 ans,res;
int mo=1e9+7;

__int64 fastmi(int p)  //快速幂
{
__int64 t=1,base=2;
while(p)
{
if(p&1) t=(t*base)%mo;
base=(base*base)%mo;
p>>=1;
}
return t;
}

int main()
{
int i,len;
while(~scanf("%s",s))
{
len=strlen(s);
ans=0;
for(i=0;i<len;i++)
ans=(ans*10+(s[i]-'0'))%(mo-1);  //小费马定理算指数
if(ans==0) ans=mo-2;  //我们算的是2^(n-1)而不是2^n 所以需要减1
else ans--;
res=fastmi(ans);
printf("%I64d\n",res);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: