Problem 1759 Super A^B mod C
Accept: 602 Submit: 2024
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
Given A,B,C, You should quickly calculate the result of A^B mod C. (1<=A,C<=1000000000,1<=B<=10^1000000).
Input
There are multiply testcases. Each testcase, there is one line contains three integers A, B and C, separated by a single space.
Output
For each testcase, output an integer, denotes the result of A^B mod C.
Sample Input
3 2 42 10 1000
Sample Output
124
Source
FZU 2009 Summer Training IV--Number Theory 1<=B<=10^1000000,看起来数据很大,unsigned long long 都无法直接存储。
指数循环节公式:a^b%c = a^( b%phic+phic )%c,具体证明过程http://hi.baidu.com/aekdycoin/item/e493adc9a7c0870bad092fd9
其中phic为c的欧拉函数,详见:http://baike.baidu.com/view/107769.htm?fr=aladdin
注:使用指数循环节公式时,需要b>c
因此判断b的大小,如果在10e10范围内,可直接用快速幂
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <sstream>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <ctime>
using namespace std;
typedef unsigned long long LL;
int geteular(int n){
int ret = 1,i;
for(i = 2;i*i<=n;i++){
if(n%i==0){
n/=i;
ret*=i-1;
}
while(n%i==0){
n/=i;
ret*=i;
}
}
if(n>1){
ret*=n-1;
}
return ret;
}
LL mul(LL a,LL b,LL c){
LL ans = 0,temp = a%c;
while(b){
// cout<<"ans"<<endl;
if(b&0x1){
if((ans+=temp)>=c){
ans-=c;
}
}
if((temp<<=1)>=c){
temp-=c;
}
b>>=1;
}
return ans;
}
LL modPow(LL a,LL b,LL m){
LL ret = 1;
while(b){
// cout<<"ret"<<endl;
if(b&1){
ret = mul(ret,a,m);
}//ret = ret*a%m;
//a = a*a%m;
a = mul(a,a,m);
b>>=1;
}
return ret;
}
char b[1100000];
int main() {
// a^b%c = a^( b%phic+phic )%c;
LL a,c;
while(scanf("%I64d%s%I64d",&a,&b,&c)!=EOF){
// LL sum = modPow(a,b,c);
// printf("%I64d\n",sum);
// }
//
int n = strlen(b);
if(n<=10){
LL numb = 0;
for(int i = 0;i<n;i++){
numb = numb*10 + b[i] - '0';
}
LL sum = modPow(a,numb,c);
printf("%I64d\n",sum);
}else{
LL phic = geteular(c);
LL numb = 0;
for(int i = 0;i<n;i++){
numb = numb%phic;
numb = numb*10 + b[i] - '0';
}
numb += phic;
LL sum = modPow(a,numb,c);
printf("%I64d\n",sum);
}
}
return 0;
}