已知长度最大为200位的正整数n,请求出2011^n的后四位。
总时间限制: 1000ms 内存限制: 65536kB
第一行为一个正整数k,代表有k组数据,k<=200接下来的k行, 每行都有一个正整数n,n的位数<=200
每一个n的结果为一个整数占一行,若不足4位,去除高位多余的0
样例输入
3
5
28
792
样例输出
1051
81
5521
#include
#include
#include
using namespace std;
long long k,a[505],x;
char c[205],s[5];
int fz(int x)
{
if (x==0) return 2011;
if (x==1) return 2011;
int t=fz(x/2)%10000;//递归分解
t=t*t%10000;//逐步平方 将乘幂分解为许多小数一步步相乘
if (x%2==1) t*=2011%10000;//x为奇数比x为偶数多乘一次底数 见知识储备
return t;
}
int main()
{
scanf("%d",&k);
for (int i=1;i<=k;i++)
{
scanf("%s",c);
if (strlen(c)>3)//如果不加这个判断 j的初始值会<0 500以下的数全部输出1
{
for (int j=strlen(c)-3;j<strlen(c);j++)
s[j-strlen(c)+3]=c[j];
x=(atoi(s))%500;//500次一循环 第500次是1 第501次是2011
} else x=(atoi(c))%500;
a[0]=1; a[1]=2011;
for (int j=2;j<=x;j++)
a[j]=fz(j)%10000;
printf("%d\n",a[x]);
}
}
输入b,p,k的值,求b^p mod k的值。其中b,p,k*k为长整型数。
输入格式:
三个整数b,p,k.
输出格式:
输出“b^p mod k=s”
s为运算结果
输入样例#1:
2 10 9
输出样例#1:
2^10 mod 9=7
很明显,对于每一个n^x,若x为偶数,则n^x=(n*n)^x/2。若x为奇数,则n^x=(n*n)^x/2*n。那么我们就能轻松的用简单的递归解决快速幂。
代码如下:
#include
#include
#include
using namespace std;
long long b,p,k,ans;
long long qpow(long long n,long long x,long long mod)
{
if(x==0) return 1;//递归出口:0次方为1
long long res=qpow(n*n%mod,x/2,mod);//递归
if(x&1) res=res*n%mod;//若x为奇数那么把返回值乘上n
return res;
}
int main()
{
scanf("%lld%lld%lld",&b,&p,&k);
ans=qpow(b,p,k);
printf("%lld^%lld mod %lld=%lld",b,p,k,ans);
return 0;
}
本题主要的难点在于数据规模很大(b,p都是长整型数),对于b^p显然不能死算,那样的话时间复杂度和编程复杂度都很大.
下面先介绍以下原理:a*b%k=(a%k)*(b%k)%k.显然有了这个原理,就可以八较大的幂分解成较小的幂,因而免去高精度计算等复杂过程.那么怎样分解最有效呢?显然对于任何一个自然数p,有p=2*p/2+p%2,如19=2*19/2+19%2=2*9+1,利用上述原理就可以把b的19次方除以k的余数转换为求b的9次方除以k的余数,即b^19=b^(2*9+1)=b*b^9*b^9,再进一步分解下去就不难求得整个问题的解
相似标程:
#include
#include
using namespace std;
int b,p,k;
int f(int); //利用分治求b^p%k
int main(){
scanf("%d%d%d",&b,&p,&k);//输入三个数
int temp=b;//将b的值备份
b%=k;//防止b太大
printf("%d^%d mod %d=%d\n",temp,p,k,f(p));
return 0;
}
int f(int p){
if(p==0){ //b^0%k=1
return 1;
}
int tmp=f(p/2)%k;
tmp=(tmp*tmp)%k; //b^p%k=(b^(p/2))^2%k
if(p%2==1){
tmp=(tmp*b)%k; //如果p为奇数,则b^p%k=((b^(p/2))^2)*b%k;
}
return tmp;
}
快速幂顾名思义,就是快速算某个数的多少次幂。
其时间复杂度为 O(log2N), 与朴素的O(N)相比效率有了极大的提高。
以下以求a的b次方来介绍
把b转换成2进制数
该2进制数第i位的权为(2^(i-1))
例如
a^11=a^(2^0+2^1+2^3)
11的二进制是1 0 1 1
11 = 2^3*1 + 2^2*0 + 2^1*1 + 2^0*1
因此,我们将a^11转化为算a^(2^0)*a^(2^1)*a^(2^3)
快速幂可以用位运算这个强大的工具实现
b & 1 //也就是取b的二进制最末位(and)
b >> 1 //就是去掉b的二进制最末位(shr 右移)
int pow3( int a, int b ) {
int r = 1, base = a;
while( b != 0 )
{
if( b & 1 )
r *= base;
base *= base;//base*base即求出了a^(2^(i-1))
b >>= 1;
}
return r;
int power4(int x, int n)
{
if (n == 0) return 1;
else
while ((n & 1) == 0)
{
n >>= 1;
x *= x;
}
int result = x;
n >>= 1;
while (n != 0)
{
x *= x;
if ((n & 1) != 0) result *= x;
n >>= 1;
}
return result;
}