hdu 4704 Sum(扩展欧拉定理)
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.
解题思路:由于指数很大,要用到欧拉降幂公式,即扩展欧拉定理:$ a^n \equiv a^{n \; mod \;\varphi(p)} (mod \; p)$,其中$gcd(a, p) = 1$。题目的意思就是给出一个N,N∈[1,10^100000],求(S1+S2+...+SN)mod(10^9+7),其中Si表示i个数相加总和为N组成的方案数,那么原问题就可以转换成N=x1+x2+x3+...+xN,其中xi看作是由m个1(m∈[0,N])相加得到的,则SN就有N个1(xi=1(i∈[1,N]))相加得到,所以也就是求N个1分组的方案数(小球隔板问题)。将N个1排成一行,有N-1个空,每个空可以选择插入或者不插入一块隔板,则一共有2^(N-1)种方案数。由于N很大,直接套整数快速幂模板肯定是不行的,又因为10^9+7是一个质数,因此是否可以通过费马小定理来实现对指数N-1先取个模,然后再套一下整数快速幂取模运算?我们来推导一下公式:根据费马小定理公式:a(p-1)≡1(mod p),其中p是质数,p不能整除a。假设n=n%(p-1)+t*(p-1),其中t=n/(p-1),则2n%p=2n%(p-1)%p*(2t)(p-1)%p,由于gcd(2t,p)=1,即(2t)(p-1)≡1(mod p),所以最终推得的公式为2n%p=2n%(p-1)%p。用字符串读取N,同时取模p-1,因为(N-1)%(p-1)=N%(p-1)-1,所以将N模p-1得到的结果N'再计算一下2(N'-1)%p即可。
AC代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const LL mod=1e9+7; 5 const int maxn=1e5+5;//N最大有10^5位 6 char str[maxn]; 7 LL mod_power(LL a,LL b){//整数快速幂 8 LL ans=1; 9 while(b){ 10 if(b&1)ans=ans*a%mod; 11 a=a*a%mod; 12 b>>=1; 13 } 14 return ans; 15 } 16 int main(){ 17 while(cin>>str){ 18 LL N=0; 19 for(int i=0;str[i]!='\0';++i) 20 N=(10*N+(str[i]-'0'))%(mod-1);//先处理N'=N%(p-1) 21 cout<<mod_power(2,N-1)<<endl;//再求2^(N'-1)%p即可 22 } 23 return 0; 24 }