HDU4704Sum 费马小定理+大数取模

题目链接

  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 }
HDU4704
原文地址:https://www.cnblogs.com/xiaozhuyang/p/HDU4704-Sum.html