描述
已知长度最大为200位的正整数n,请求出2011^n的后四位。
输入
第一行为一个正整数k,代表有k组数据,k<=200接下来的k行,
每行都有一个正整数n,n的位数<=200
输出
每一个n的结果为一个整数占一行,若不足4位,去除高位多余的0
样例输入
3 5 28 792
样例输出
1051 81 5521
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
char a[201];
int f(int n) //快速幂 ,求2011的n次方并求余10000;
{
if(n==0)return 1;
if(n==1)return 2011;
int b=f(n/2)%10000;
b=(b*b)%10000;
if(n%2==1)b=(b*2011)%10000;
return b;
}
int main()
{
int l,k,x=0;
cin>>k;
for(int i=1;i<=k;++i)
{
x=0;
memset(a,0,sizeof(a));//一定要赋初值0
scanf("%s",a);
l=strlen(a);
if(l==1)x=a[0]-'0'; //将字符串转为数字;
else if(l==2)x=10*(a[0]-'0')+(a[1]-'0');
else if(l==3)x=100*(a[0]-'0')+10*(a[1]-'0')+(a[2]-'0');
else for(int i=l-4;i<=l-1;++i)
x=x*10+(a[i]-'0');
cout<<f(x)<<endl;
}
return 0;
}
使用了分治的思想,通过递归调用自身来计算幂运算。在每次递归中,将指数n除以2,然后递归计算f(n/2)的结果,直到n为0或1时返回基本情况的结果。然后根据n的奇偶性进行相应的乘法操作,最后返回最终结果。
这种快速幂算法的时间复杂度为O(log n),相比普通的幂运算方法(时间复杂度为O(n)),可以显著提高计算效率。
int b=f(n/2)%10000;
b=(b*b)%10000;
首先,int b = f(n / 2) % 10000;
这行代码将n除以2,并将结果传递给函数f进行递归调用。然后,取模10000的操作是为了确保结果在0到9999之间,避免溢出。
接下来,b = (b * b) % 10000;
这行代码将b平方后取模10000。这是因为2011的n次方可以表示为2011的n/2次方乘以自身。通过这种方式,我们可以将问题规模缩小一半,从而减少计算量。
最后,如果n是奇数,还需要再乘以2011并取模10000,即 if (n % 2 == 1) b = (b * 2011) % 10000;
。这是因为当n为奇数时,我们需要额外乘以一个2011来得到正确的结果。
综上所述,这样的操作是为了利用分治的思想,将问题规模缩小一半,并通过递归调用函数f来计算2011的n次方并求余10000。
if (n % 2 == 1) b = (b * 2011) % 10000;
在快速幂算法中,当指数 n
是奇数时,我们需要在已经计算出的 2011^(n/2)
的基础上再乘以一个 2011
来得到最终结果。这是因为:
- 如果
n
是偶数,那么2011^n = (2011^(n/2))^2
。 - 如果
n
是奇数,那么2011^n = 2011 * (2011^(n/2))^2
。
因此,对于奇数 n
,我们已经有了 (2011^(n/2))^2
的结果,只需要再乘以一个 2011
即可。
这里的 b = (b * 2011) % 10000;
行代码就是实现这个乘以 2011
并取模 10000
的操作。取模操作是为了确保结果不会因为数值过大而溢出,同时它也符合题目的要求——求余 10000
。
总结一下,这行代码的目的是处理指数为奇数的情况,确保能够正确计算出 2011^n mod 10000
的值。