题目大意,已知f(0) = 1 且 f(n) = (n%10)^f(n/10) ,
输入n,m, 输出 f(n)%m ---- (2 ≤ n , m ≤ 10^9)
要应用到一道公式
其中phi()为欧拉函数,当条件成立时,可以利用该公式进行加速幂
AC大神的blog有对于此公式的详细证明: http://hi.baidu.com/aekdycoin/blog/item/b6f1762565bb403fc8955908.html
然后注意公式使用的条件,注意一下0^0=1, 处理好细节就能过了
当然我没试过单纯快速幂能不能过,应该是没什么问题的,感觉这题数据强度不是太大
不过对于HDU 3609 和 09上海区预赛B题,(hdu 3221), 就必须用到了
#include<iostream>
using namespace std;
char n[10];
int m[10];
__int64 eular(__int64 num)
{
__int64 ret=1;
for(int i=2;i*i<=num;i++)
{
if(num%i==0)
{
num/=i;ret*=i-1;
while(num%i==0) {num/=i;ret*=i;}
}
}
return num>1? ret*(num-1):ret;
}
__int64 power(__int64 num,__int64 k,__int64 mod)
{
if(num==0)
{
if(k!=0) return 0;
else return 1;
}
__int64 res=1;
while(k)
{
if(k&1)
{
res=res*num%mod;
if(res==0) res=mod;
}
num= (num%mod) * (num%mod) % mod;
k>>=1;
}
return res;
}
void init(int mm,int l)
{
m[1]=mm;
for(int i=2;i<=l+1;i++)
m[i]=eular(m[i-1]);
}
int main()
{
int tt,mo;
scanf("%d",&tt);
while(tt--)
{
scanf("%s%d",&n,&mo);
int l=strlen(n);
init(mo,l);
__int64 ans=1;
for(int i=0;i<l;i++)
{
if(ans!=0)
{
ans%=m[l-i];
if(ans==0) ans=m[l-i];
}
ans=power(n[i]-'0',ans,m[l-i]);
}
printf("%I64d\n",ans);
memset(n,0,sizeof(0));
}
return 0;
}