题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=4704
题目大意:
看似复杂,其实就是求整数n的划分数,4=1+1+2和4=1+2+1是不同的。因而可知答案是2n-1。
题目分析:
因为n实在是太大太大了,这可咋办啊?!n<10100000。
做这场的时候没有注意到,也是当时没有看过什么是费马小定理,居然跟模值有关系!mod=1000000007。这个mod有什么特点呢?它是个质数。
费马小定理揭示了:当p是一个素数并且a和p互质时,ap-1 %p≡1。
那么在这道题里a=2,p=mod。显然满足费马小定理。再根据同余模定理,
当n>p时:设m=n-p。那么an-1=am+p-1=ap-1*am。因而an-1%p=am+p-1%p=((ap-1%p )*(am%p))%p=1*am%p。
这么我们就可以断定mod-1是一个循环节。先用大数对它取模,然后数据量就可以承受得起了,再用快速幂,这道题就解了!
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 const int MAX=100005; 6 const int mod=1000000007; 7 char s[MAX]; 8 9 long long pow(long long a,long long b) 10 { 11 long long base=a,r=1; 12 while(b!=0) 13 { 14 if(b&1) r=(r*base)%mod; 15 base=(base*base)%mod; 16 b>>=1; 17 } 18 return r%mod; 19 } 20 21 int main() 22 { 23 while(scanf("%s",s)!=EOF) 24 { 25 int len=strlen(s); 26 long long num=0; 27 for(int i=0;i<len;i++)//大数取模 28 num=(num*10+(int)(s[i]-'0'))%(mod-1); 29 if(num==0)//说明num=mod-1 30 { 31 cout<<pow(2,mod-2)<<endl; 32 } 33 else 34 { 35 num--; 36 cout<<pow(2,num)<<endl; 37 } 38 } 39 return 0; 40 }