zoukankan      html  css  js  c++  java
  • POJ 3243 Clever Y (求解高次同余方程A^x=B(mod C) Baby Step Giant Step算法)

    不理解Baby Step Giant Step算法,请戳:

    http://www.cnblogs.com/chenxiwenruo/p/3554885.html

    #include <iostream>
    #include <stdio.h>
    #include <math.h>
    #include <string.h>
    #define SIZE 99991
    /*
    POJ 3243
    AC
    求解同余方程:
    A^x=B(mod C)
    */
    using namespace std;
    struct HashTable{
        int key[SIZE];  //对应A^i
        int val[SIZE];  //对应i
        void init(){
            memset(key,-1,sizeof(key));
            memset(val,-1,sizeof(val));
        }
        int hfind(int k){
            int kk=k%SIZE;
            while(key[kk]!=k && key[kk]!=-1){
                kk=(kk+1)%SIZE; //原先写成了kk=(kk+1)&SIZE;导致一直TLE。。。
            }
            return val[kk];
        }
        void hinsert(int v,int k){
            int kk=k%SIZE;
            while(key[kk]!=-1 && key[kk]!=k){
                kk=(kk+1)%SIZE;
            }
            if(key[kk]==-1){
                key[kk]=k;
                val[kk]=v;
            }
        }
    }h;
    
    int gcd(int a,int b){
        return b==0?a:gcd(b,a%b);
    }
    int exgcd(int a,int b,int &x,int &y){
        if(b==0){
            x=1;
            y=0;
            return a;
        }
        int d=exgcd(b,a%b,x,y);
        int tmp=x;
        x=y;
        y=tmp-a/b*y;
        return d;
    }
    
    //求解ax=b(mod c),
    int solvex(int a,int b,int c){
        int x,y;
        int d;
        d=exgcd(a,c,x,y);
        //注意这里要强制转换成long long,不然x*b会超出int范围
        x=((long long)x*b%c+c)%c;
        //x=((long long)x*(b/d)%(c/d)+c/d)%(c/d); //实际应该是这样,但由于传的参数D,B,C中,D、C互质,d=1。
        return x;
    }
    long long quickPow(long long a,int b,int mod){
        long long ret=1%mod;
        a=a%mod;
        while(b){
            if(b&1)
                ret=(ret*a)%mod;
            a=(a*a)%mod;
            b=b>>1;
        }
        return ret;
    }
    int BabyStep(int A,int B,int C){
        B=B%C;  //注意这里先要将B对C取模
        h.init();
        int d=0;
        long long D=1%C,buf=D;
        for(int i=0;i<=100;buf=buf*A%C,++i){
            if(buf==B)
                return i;
        }
        int tmp;
        while((tmp=gcd(A,C))!=1){
            if(B%tmp)
                return -1;
            d++;
            B=B/tmp;
            C=C/tmp;
            D=D*A/tmp%C;
        }
        int m=(int)ceil(sqrt((double)C));
        buf=1%C;
        for(int i=0;i<m;buf=buf*A%C,++i){
            h.hinsert(i,(int)buf);
        }
        long long K=quickPow((long long)A,m,C);
        for(int i=0;i<m;D=D*K%C,++i){
            int ans=solvex((int)D,B,C);
            int j=h.hfind(ans);
            if(j!=-1)
                return i*m+j+d;
        }
        return -1;
    }
    int main()
    {
        int A,B,C;
        while(scanf("%d%d%d",&A,&C,&B)!=EOF){
            if(A==0 && B==0 && C==0)
                break;
            int ans=BabyStep(A,B,C);
            if(ans==-1)
                printf("No Solution
    ");
            else
                printf("%d
    ",ans);
        }
        return 0;
    }
    View Code

    该题和POJ 2417,HDU 2815 一样,代码稍微改改就能AC。

    不过不同的是,HDU 2815  若B>=C,则要判断无解。而不是像POJ这两道题,要先B%C一下。

  • 相关阅读:
    自制游戏Zombie代码
    HNOI2020总结
    20200615题解:继续扮演
    20200611题解:树网的核
    历次考试总结
    寒假总结和省选大体规划
    每日总结
    有一种感动叫ACM(记WJMZBMR在成都赛区开幕式上的讲话)
    递推求欧拉函数的最简单的详解
    总结一些好用的C++小技巧
  • 原文地址:https://www.cnblogs.com/chenxiwenruo/p/3554894.html
Copyright © 2011-2022 走看看