【题目描述】
已知长度最大为200位的正整数n,请求出2011n的后四位。
【输入】
第一行为一个正整数k,代表有k组数据(k≤200),接下来的k行,每行都有一个正整数n,n的位数≤200。
【输出】
每一个n的结果为一个整数占一行,若不足4位,去除高位多余的0。
【输入样例】
3
5
28
792
【输出样例】
1051
81
5521
题目分析:
一看到题目就知道这必须要写一个快速幂,但次数最高是200位,超了long long 肯定是要用字符数组来储存。题目要求给出后四位数字,这就会想到%10000.因为当模上任何数,最终结果肯定小于被模数,这和进制转换有点类似。既然都%10000了,肯定是有一个规律的,至于为何有规律,我也想不明白,总是感觉不可能随着次数的增加结果会一直变化吧。
那么现在的问题就是怎么找这个规律,所以我就在想啊,可不可以让一个数不断的乘2011,再不断的%10000,只要找到最后结果和2011%10000结果一样的数就可以证明这是一个自带周期的数列。
找规律的代码如下:
int a=1,b=1;
while(1)
{
a*=2011;
a%=10000;
if(b!=1&&a==2011){
cout<<b;
break;}
b++;
}
最后结果是501,可知每500个数结果一循环。
所以只需看这次数的最后三位即可。因为500一循环,所以大于500的数都可以减500.
代码:
#include<iostream>
#include<cstring>
using namespace std;
int power(int a,int b)
{
if(b==0) return 1;
int temp=power(a,b/2)%10000;
temp=(temp*temp)%10000;
if(b%2==1)
temp*=a%10000;
return temp%10000;
}
int main()
{
int t,e=1;
char n[201];
cin>>t;
while(t--)
{
cin>>n;
e=1;
int len=strlen(n),shu=0;
if(len>3)
{
for(int i=len-1;i>=len-3;i--)
{
shu+=(n[i]-'0')*e;
e*=10;
}
if(shu>500) shu-=500;
}
if(len<=3)
for(int i=len-1;i>=0;i--)
{
shu+=(n[i]-'0')*e;
e*=10;
}
cout<<power(2011,shu)%10000<<endl;
}
return 0;
}