2011的n次方

题目:http://noi.openjudge.cn/ch0204/2991/

总时间限制:1000ms  内存限制: 65536kB
描述
已知长度最大为200位的正整数n,请求出2011^n的后四位。
输入
第一行为一个正整数k,代表有k组数据,k<=200接下来的k行,

每行都有一个正整数n,n的位数<=200
输出
每一个n的结果为一个整数占一行,若不足4位,去除高位多余的0
样例输入
3
5
28
792
样例输出
1051
81
5521

参考:

利用循环节:http://m.blog.csdn.net/u013675643/article/details/51820648

高精度除法:http://blog.csdn.net/qq_35479641/article/details/51810945

 

下面的思路参照循环节的做法。

题目只需要输出后四位,因此答案必然有一个最多5位数的循环节。于是可以先写个暴力去找循环节,发现循环节长度为500,这个数就很好处理了。后面读入n时只保留后三位数,再mod500就得出答案了,比写高精度简单多了~

 1 #include<stdio.h>
 2 #include<string.h>
 3 // m^n % k
 4 long long quickpow(long long m,long long n,long long k)
 5 {
 6     long long ans = 1;
 7     while (n > 0)
 8     {
 9           if (n & 1)
10              ans = (ans*m)%k;
11           n = n >> 1 ;
12           m = (m*m)%k;
13     }
14     return ans;
15 }
16 int main(int argc, char *argv[])
17 {
18     int k;
19     int i;
20     char n[205];
21     int N,len;
22     scanf("%d",&k);    
23     for(i=0;i<k;i++)
24     {
25         scanf("%s",n);getchar();
26         N=0;
27         len=strlen(n);
28         N=n[len-1]-'0';
29         if(len>=2) N=(n[len-2]-'0')*10+N;
30         if(len>=3) N=(n[len-3]-'0')*100+N;
31         if(len>=4) N=(n[len-4]-'0')*1000+N;
32         N=N%500;
33         printf("%lld\n",quickpow(2011,N,10000));
34     }
35     return 0;
36 }

 暴力寻找循环节的一个简单操作:

 1 #include <stdio.h>
 2 
 3 long long quickpow(long long m,long long n,long long k)//返回m^n % k的结果 
 4 {
 5     long long ans = 1;
 6     while (n > 0)
 7     {
 8           if (n & 1)
 9              ans = (ans*m)%k;
10           n = n >> 1 ;
11           m = (m*m)%k;
12     }
13     return ans;
14 }
15 int main(int argc, char *argv[])
16 {
17     freopen("data.txt","w",stdout);
18     int A[10005],B[10005];
19     for(int i=1;i<10005;i++)
20     {
21         //printf("%d\n",quickpow(2011,i,10000));
22         A[i]=quickpow(2011,i,10000);
23     }
24     
25     for(int i=1;i<10005;i++)
26     {
27         for(int j=i+1;j<10005;j++)
28         {
29             if(A[i]==A[j]) { B[i]=j;break; }
30         }
31     }
32     for(int i=1;i<10005;i++)
33     {
34         printf("%d %d\n",A[i],B[i]);
35     }
36     return 0;
37 }
View Code

 

 

还有一个数学论证:http://blog.csdn.net/li744831579/article/details/8784547

 

posted on 2017-06-17 21:32  华山青竹  阅读(1686)  评论(0编辑  收藏  举报

导航