1234:2011
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 7002 通过数: 2979
【题目描述】
已知长度最大为200位的正整数n,请求出2011^n的后四位。
【输入】
第一行为一个正整数k,代表有k组数据(k≤200),接下来的k行,每行都有一个正整数n,n的位数≤200。
【输出】
每一个n的结果为一个整数占一行,若不足4位,去除高位多余的0。
【输入样例】
3
5
28
792
【输出样例】
1051
81
5521
【分析】
依题意,求2011^n的后四位。后四位显然是模10000。2011^n%10000,可以直接套用蒙哥马利幂取模模板。
模板1:蒙哥马利幂取模(非递归)
幂取模 a^b mod n 非递归
long long mod_exp(long long a,long long b,long long n)
{
long long res=1;
while(b)
{
if(b&1)
res=res*a%n;
a=a*a%n; // 反复平方
b>>=1; // 2分求幂
}
return res;
}
模板很好理解,用到的就是反复平方法和二分求幂法,例如:求(2^100)%10的最后一位是多少?
(2^100)%10 = (4^50)%10 = (16^25)%10 = (16%10)^25%10 = (6^25)%10 = (6*6^24)%10 = (6*36^12)%10 = ... = 6。
模板2:蒙哥马利幂取模(递归1)
幂取模 m^n mod p 递归1
long long mod_exp(long long m,long long n,long long p)
{
long long t;
if(n==1)
return m%p;
t=mod_exp(m,n/2,p)%p;
t=t*t%p;
if(!(n&1)) // 等价 if(n%2==0)
return t;
else
return m*t%p;
}
模板3:蒙哥马利幂取模(递归2)
幂取模 m^n mod p 递归2
long long mod_exp(long long m,long long n,long long p)
{
long long t;
if(n==1)
return m%p;
if(n%2==0)
return mod_exp( (m*m)%p , n/2 , p);
else
return m*mod_exp(m%p, n-1, p)%p;
}
【参考代码】
#include<stdio.h>
#include<string.h>
#define MAXN 210
char s[MAXN];
//蒙哥马利幂取模非递归模板
long long quickpow(long long a,long long b,long long n) // a^b mod n
{
long long res=1;
while(b) //2分求幂法
{
if(b & 1)
res=res*a%n;
a=(a*a)%n; //反复平方法
b>>=1;
}
return res;
}
int main()
{
int i,k,len,n;
scanf("%d",&k);
getchar();
while(k--)
{
gets(s);
n=0;
len=strlen(s);
n=s[len-1]-'0';
if(len>=2)
n+=(s[len-2]-'0')*10;
if(len>=3)
n+=(s[len-3]-'0')*100;
if(len>=4)
n+=(s[len-4]-'0')*1000;
n%=500;
printf("%lld\n",quickpow(2011,n,10000));
}
return 0;
}