• Root(hdu5777+扩展欧几里得+原根)


    Root

                                                                             Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
                                                                                                               Total Submission(s): 34    Accepted Submission(s): 6


    Problem Description
    Given a number sum(1sum100000000),we have m queries which contains a pair (xi,yi) and would like to know the smallest nonnegative integer kisatisfying xkii=yi mod p when the prime number p (sum mod p=0)(ps:00=1)
     

    Input
    The first line contains a number T, indicating the number of test cases. 

    For each case, each case contains two integers sum,m(1sum100000000,1m100000) in the first line. 

    The next m lines will contains two intgeers xi,yi(0xi,yi1000000000)
     

    Output
    For each test case,output "Case #X:" and m lines.(X is the case number) 

    Each line cotain a integer which is the smallest integer for (xi,yi) ,if we can't find such a integer just output "-1" without quote.
     

    Sample Input
    1 175 2 2 1 2 3
     

    Sample Output
    Case #1: 0 3
    Hint
    175 =527 20 mod 5 = 1 23 mod 7 = 1 So the answer to (2,1) is 0
     

    Source



    比較经典一道扩展欧几里得 



    如今。我们首先来解决下原根的问题:简单的解释能够參考:>>原根<<  

     

    资源下载:http://download.csdn.net/detail/u010579068/8993383


    不急看懂的,能够先去切道 定义题    链接:1135 原根  

     解题 http://www.cnblogs.com/yuyixingkong/p/4722821.html



    转载请注明出处:寻找&星空の孩子     

     题目链接:http://acm.hdu.edu.cn/showproblem.php?

    pid=5377



    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<map>
    using namespace std;
    typedef long long ll;
    const int maxn=1e6+1;
    const int maxv=1e5+1;
    bool isnp[maxv];
    int prime[maxv],pnum;//素数数组,素数个数
    int cas;
    void get_prime()//素数打表
    {
        pnum=0;
        int i,j;
        memset(isnp,0,sizeof(isnp));
        isnp[0]=isnp[1]=true;
        for(i=2; i<maxv; i++)
        {
            if(!isnp[i])prime[pnum++]=i;
            for(j=0; j<pnum&&prime[j]*i<maxv; j++)
            {
                isnp[i*prime[j]]=true;
                if(i%prime[j]==0)break;
            }
        }
    }
    ll qukpow(ll k,ll base,ll p)
    {
        ll res=1;
        for(; k; k>>=1)
        {
            if(k&1)res=(res*base)%p;
            base=(base*base)%p;
        }
        return res;
    }
    ll ppow(ll a,ll b,ll mod)
    {
        ll c=1;
        while(b)
        {
            if(b&1) c=c*a%mod;
            b>>=1;
            a=a*a%mod;
        }
        return c;
    }
    ll fpr[maxv];
    
    ll find_primitive_root(ll p)//求p的原根    g^(p-1) = 1 (mod p); 求g
    {
        ll cnt=0,num=p-1,res;
        int i;
        if(p==2)return 1;
        for(i=0; i<pnum && prime[i]*prime[i]<=num && num>1 ; i++)
        {
            if(num%prime[i]==0)//
            {
                fpr[cnt++]=prime[i];
                while(num%prime[i]==0)num/=prime[i];
            }
        }
        if(num>1)fpr[cnt++]=num;//fpr[]存的是p-1的因子
        for(res=2; res<=p-1; res++)//暴力
        {
            for(i=0; i<cnt; i++)
                if(ppow(res,p/prime[i],p)==1)break;
            if(i>=cnt)return res;
        }
        return -1;
    };
    
    const int mod=1e6+7;
    
    struct solve
    {
        struct HashTable
        {
            int top,head[mod];
            struct Node
            {
                int x,y,next;
            } node[mod];
            void init()
            {
                top=0;
                memset(head,0,sizeof(head));
            }
            void insert(ll x,ll y)
            {
                node[top].x=x;
                node[top].y=y;
                node[top].next=head[x%mod];
                head[x%mod]=top++;
            }
            ll query(ll x)
            {
                for(int tx=head[x%mod]; tx; tx=node[tx].next)
                    if(node[tx].x==x)return node[tx].y;
                return -1;
            }
        } mp;
    
        ll p;
        ll discretelog(ll prt,ll a) //取对数
        {
            ll res,am=ppow(prt,maxn-1,p),inv=ppow(a,p-2,p),x=1;
            for(ll i=maxn-1;; i+=(maxn-1))
            {
                if((res=mp.query((x=x*am%p)*inv%p))!=-1)
                {
                    
                    return i-res;
                }
                if(i>p)break;
            }
            return -1;
        }
        void ex_gcd(ll a,ll b,ll &d,ll &x,ll &y)//扩展欧几里得 x为最后须要的k
        {
            if(!b)
            {
                d=a;
                x=1;
                y=0;
            }
            else
            {
                ex_gcd(b,a%b,d,y,x);
                y-=x*(a/b);
            }
        }
    
        ll proot;
        void init()
        {
            mp.init();
            ll tmp,x,y,d;
            int i;
            proot=find_primitive_root(p);//找到素数p的原根
            for(i=0,tmp=1; i<maxn-1; i++,tmp=tmp*proot%p)
                mp.insert(tmp%p,i*1ll);
        }
        ll query(ll x,ll y)
        {
            ll d;
            x%=p;
            y%=p;
            
            if(y==1)return 0;
            else if(x==0)
            {
                if(y==0)return 1;
                else return -1;
            }
            else if(y==0)return -1;
            else
            {
                ll s=discretelog(proot,x);
                
                ll t=discretelog(proot,y);
                
                ex_gcd(s,p-1,d,x,y);
                if(t%d)return -1;
                else
                {
                    ll dx=(p-1)/d;
                    x=(x%dx+dx)%dx;
                    x*=(t/d);
                    x=(x%dx+dx)%dx;
                    return x;
                }
            }
        }
    } sol[32];
    int main()
    {
        int i,j,q,con,T;
        ll sum,x,y;
        scanf("%d",&T);
        get_prime();
        cas=1;
        while(cas<=T)
        {
            con=0;
            scanf("%I64d %d",&sum,&q);
    
            for(i=0; i<pnum&&prime[i]*prime[i]<=sum&&sum!=1; i++)
            {
                if(sum%prime[i]==0)//素数存起来
                {
                    sol[con].p=prime[i];
                    sol[con].init();
                    con++;
                    while(sum%prime[i]==0)sum/=prime[i];
                }
            }
            if(sum>1)
            {
                sol[con].p=sum;
                sol[con].init();
                con++;
            }
    
            printf("Case #%d:
    ",cas++);
    
            for(i=0; i<q; i++)
            {
                scanf("%lld %lld",&x,&y);
    
                ll res=1e18,tmp;
                for(j=0; j<con; j++)
                {
     
                    tmp=sol[j].query(x,y);
                    if(tmp!=-1)res=min(res,tmp);
                }
                if(res==1e18)res=-1;
                printf("%I64d
    ",res);
            }
        }
        return 0;
    }
    



  • 相关阅读:
    Linux常用命令
    C# 报表设计器 (winform 设计端)开发与实现生成网页的HTML报表
    完成复杂表头列表
    流程设计--页面介绍
    流程设计--设计理念
    报表设计--坐标实例-位移坐标
    Spring MVC 工作原理--自我理解
    java ==、equals和hashCode的区别和联系
    java 自动装箱和拆箱
    java maven笔记
  • 原文地址:https://www.cnblogs.com/blfbuaa/p/6773801.html
Copyright © 2020-2023  润新知