hdu 5187高速べき乗

2225 ワード

タイトル:http://acm.hdu.edu.cn/showproblem.php?pid=5187 あなたにn個の数をあげて、それからこのn個の数を並べて、規則は先に上がってから下がるか、先に下がってから上がるかです.分析:実は法則はとても簡単で、極値を確定すれば、順序は一定です.しかし、n,pの範囲に注意してください.例えばn=1,p=1の場合である.全部でn個の位置があり、位置ごとに2種類選択され、合計2^nのうち、頭と尾がそれぞれ繰り返される1つを減算します.n,pの範囲は(1≦n,p≦1018)なので,直接乗算するとオーバーフローするので,バイナリ乗算に分解する
#include<cstdio>
#include<cstring>
typedef long long ll;
ll mul(ll a,ll b,ll c) //a*b   ,   b      ,    
{
    ll res=0;
    for(;b;b>>=1){
        if(b&1){
            res+=a;
            while(res>=c)res-=c;
        }
        a<<=1;
        while(a>=c)a-=c;
    }
    return res;
}
ll qmod(ll a,ll n,ll p)
{
    ll ans=1;
    for(;n;n>>=1){
        if(n&1)ans=mul(ans,a,p);
        a=mul(a,a,p);
    }
    return ans;
}
int main()
{
    ll n,p;
    while(~scanf("%I64d%I64d",&n,&p)){
        if(n==1)printf("%d
"
,n%p); else printf("%I64d
"
,(qmod(2ll,n,p)-2+p)%p); } return 0; }