hdu 2837 Calculation (指数循环节+欧拉函数)
题意:
Assume that f(0) = 1 and 0^0=1. f(n) = (n)^f(n/10) for all n bigger than zero. Please calculate f(n)%m. (2 ≤ n , m ≤ 10^9, x^y means the y th power of x).
思路:指数循环节。
trick点在于0^0=1这点。
比较容易想到的一层是ksm的时候特判。
比较不容易想到的一层是,0作为底数的时候,可能出现0^a在用降幂公式加速后,出现0^0。
举个例子:
680 80
phi(80)=32,恰好是8^6的因子
而0^(8^6)答案应该为0,用降幂公式加速后变成了0^0,答案变成了1,结果错误
究其原因,是因为这道题中底数可能有0以及0^0是题目中定义的运算。
解决办法是ksm的结果判断一下,如果是0就加mod。
/* ***********************************************
Author :111qqz
Created Time :Sun 30 Oct 2016 07:19:02 PM CST
File Name :code/hdu/2837.cpp
************************************************ */
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cstdlib>
#include <ctime>
#define fst first
#define sec second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ms(a,x) memset(a,x,sizeof(a))
typedef long long LL;
#define pi pair < int ,int >
#define MP make_pair
using namespace std;
const double eps = 1E-8;
const int dx4[4]={1,0,0,-1};
const int dy4[4]={0,-1,1,0};
const int inf = 0x3f3f3f3f;
LL n,m;
LL digit[20];
int cnt;
LL ksm( LL a,LL b,LL mod)
{
// cout<<"a:"<<a<<" b:"<<b<<" mod:"<<mod<<" ";
if (b==0) return 1;
if (a==0) return 0; //任何数的0次方都为1,0的任何除0外次方等于0.
LL res = 1;
while (b>0)
{
if (b&1) res = ( res * a) % mod;
b = b >> 1LL;
a = ( a*a) % mod;
}
// if (res<mod) res = res+mod;
if (res==0) res = mod;
// cout<<" res:"<<res<<endl;
return res;
}
LL euler( LL x)
{
LL ret = 1;
for ( LL i =2 ; i * i <= x ; i++)
{
if (x%i==0)
{
x/=i;
ret*=(i-1);
while (x%i==0)
{
x/=i;
ret*=i;
}
}
}
if (x>1) ret*=(x-1);
return ret;
}
LL fun( LL n,LL m)
{
if (n<10) return n;
LL x = fun(n/10,euler(m));
// cout<<"n:"<<n<<" m:"<<m<<" x:"<<x<<endl;
if (x>=euler(m)) x = x%euler(m) + euler(m);
return ksm(n,x,m);
}
int main()
{
#ifndef ONLINE_JUDGE
// freopen("code/in.txt","r",stdin);
#endif
int T;
cin>>T;
while (T--)
{
scanf("%lld%lld",&n,&m);
printf("%lld\n",fun(n,m)%m);
}
#ifndef ONLINE_JUDGE
fclose(stdin);
#endif
return 0;
}