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 }

 

posted @ 2018-08-06 18:03  霜雪千年  阅读(258)  评论(0编辑  收藏  举报