首页 > 其他 > 详细

【bzoj2242】: [SDOI2011]计算器 数论-快速幂-扩展欧几里得-BSGS

时间:2017-03-19 11:00:54      阅读:230      评论:0      收藏:0      [点我收藏+]

1.快速幂

2.扩展欧几里得(费马小定理)

3.BSGS

/* http://www.cnblogs.com/karl07/ */
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;

#define LL long long
int T,K;
LL a,b,p;

LL Q_tim(LL x,LL y,LL p){
    LL ans=0;
    while (y){
        if (y&1) ans=(ans+x)%p;
        x=(x+x)%p;
        y=(y>>1);
    }
    return ans;
}

LL Q_pow(LL x,LL y,LL p){
    LL ans=1;
    while (y){
        if (y&1) ans=ans*x%p;
        x=x*x%p;
        y=(y>>1);
    }
    return ans;
}

void ex_gcd(LL a,LL b,LL &x,LL &y,LL &gcd){
    if (b==0) {gcd=a;x=1;y=0;return;}
    ex_gcd(b,a%b,y,x,gcd);
    y-=x*(a/b);
}

void p2(LL a,LL b,LL p){
    LL x,y,gcd,g,ans=p+1;
    ex_gcd(a,p,x,y,gcd);
    if (b%gcd!=0){ puts("Orz, I cannot find x!"); return;}
    ex_gcd(a/gcd,p/gcd,x,y,g);
    x=x*(b/gcd)%p;
    x=(x+p)%p;
    printf("%lld\n",x);
}

void BSGS(LL a,LL b,LL p){
    if ((a==0 && b!=0) || (a==1 && b!=1)) { puts("Orz, I cannot find x!"); return;}
    LL sz=(LL)ceil(sqrt(p)),inv,e=1;
    map<LL,LL> x;
    x.clear();
    x[1]=0;inv=Q_pow(Q_pow(a,sz,p),p-2,p);
    for (int i=1;i<sz;i++) {e=Q_tim(e,a,p); if (!x.count(e)) x[e]=i;}
    for (int i=0;i<sz;i++) {
        if (x.count(b)) {printf("%lld\n",i*sz+x[b]); return;}
        b=Q_tim(b,inv,p);
    }
    puts("Orz, I cannot find x!");
}

int main(){
    scanf("%d%d",&T,&K);
    for (int i=1;i<=T;i++){
        scanf("%lld%lld%lld",&a,&b,&p);
        if (K==1) printf("%lld\n",Q_pow(a%p,b,p));
        if (K==2) p2(a%p,b%p,p);
        if (K==3) BSGS(a%p,b%p,p);
    }
    return 0;
}

 

【bzoj2242】: [SDOI2011]计算器 数论-快速幂-扩展欧几里得-BSGS

原文:http://www.cnblogs.com/karl07/p/6577586.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!