HDU 2837 Calculation (指数循环节)

来源:互联网 发布:手机视频解码软件 编辑:程序博客网 时间:2024/05/16 05:02

 题目大意,已知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;}


 

 

 

原创粉丝点击